You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue+Element UI实现Graph API大附件后台懒加载下载方案咨询

大附件下载优化方案(Vue + Element UI)

问题背景

  • 最初通过base64生成data URL直接下载,40MB附件耗时超3分钟,性能极差
  • 改用Graph API的$value接口懒加载后,仍需约1分钟完成下载,无法达到类似云盘的后台下载体验

原有实现代码

最初的a标签实现

<a :download="scope.row.name" :href="`data:${scope.row.type};base64,${scope.row.contentBytes}`">download</a>

当前的$value请求实现

graphapi.js

export function getAttachment(eventId, attachmentId) {
  return request({
    url: `/events/${eventId}/attachments/${attachmentId}/$value`,
    method: 'get'
  })
}

form.vue 模板部分

<el-table-column v-if="action === 'edit'" width="150px" label="操作">
  <template slot-scope="scope">
    <el-button size="small" type="text">
      <a @click.prevent="downloadAttachment(scope.row.id)">download</a>
    </el-button>
    <el-button size="small" type="text" @click="deleteAttachment(scope.row.id)">remove</el-button>
  </template>
</el-table-column>

form.vue 脚本部分

downloadAttachment(attachmentId) {
  const attachment = getAttachment(this.$route.params.id, attachmentId)
  const link = document.createElement('a')
  link.href = `data:${attachment.type};base64,${attachment.contentBytes}`
  link.click()
},

优化后的实现方案

1. 修改Graph API请求配置

核心是指定responseType: 'blob'直接获取二进制数据,避免base64转换开销:

// graphapi.js
export function getAttachment(eventId, attachmentId, fileName, fileType) {
  return request({
    url: `/events/${eventId}/attachments/${attachmentId}/$value`,
    method: 'get',
    responseType: 'blob', // 关键:返回二进制blob类型
    onDownloadProgress: (progressEvent) => {
      // 可选:添加下载进度监听,可用于展示进度条
      const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
      console.log(`下载进度:${percentCompleted}%`)
    }
  }).then(blob => {
    return { blob, fileName, fileType }
  })
}

2. 重写前端下载逻辑

基于blob生成下载链接,即时触发浏览器原生下载:

// form.vue 脚本部分
async downloadAttachment(attachmentId) {
  try {
    // 从表格数据中获取附件的文件名、类型(如果已存在)
    const targetRow = this.tableData.find(item => item.id === attachmentId)
    if (!targetRow) return this.$message.error('附件不存在')

    const { blob, fileName } = await getAttachment(
      this.$route.params.id,
      attachmentId,
      targetRow.name,
      targetRow.type
    )

    // 创建下载链接并触发下载
    const downloadUrl = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = downloadUrl
    link.download = fileName
    document.body.appendChild(link)
    link.click()

    // 清理资源
    setTimeout(() => {
      window.URL.revokeObjectURL(downloadUrl)
      document.body.removeChild(link)
    }, 100)
  } catch (err) {
    this.$message.error('下载失败,请重试')
    console.error(err)
  }
}

3. 模板部分无需修改

原有的表格操作列代码保持不变,仅修改downloadAttachment方法的内部逻辑即可。


优化原理

  1. 消除base64转换开销:base64会让文件体积增大30%,且大文件的编码/解码会占用大量前端资源,直接使用blob可避免此问题
  2. 流式处理二进制数据:浏览器可边接收数据边处理,无需等待全部数据加载完成再触发下载
  3. 原生下载体验:利用浏览器原生下载机制,用户能看到系统级的下载进度条,接近云盘的后台下载效果

内容的提问来源于stack exchange,提问作者Sanji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:20:26