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方法的内部逻辑即可。
优化原理
- 消除base64转换开销:base64会让文件体积增大30%,且大文件的编码/解码会占用大量前端资源,直接使用blob可避免此问题
- 流式处理二进制数据:浏览器可边接收数据边处理,无需等待全部数据加载完成再触发下载
- 原生下载体验:利用浏览器原生下载机制,用户能看到系统级的下载进度条,接近云盘的后台下载效果
内容的提问来源于stack exchange,提问作者Sanji
相关产品推荐
相关产品推荐

