使用Axios下载600MB以上大Blob文件为空,如何正确实现大文件下载
Axios大文件下载空文件问题解决方案
核心原因
你遇到的空文件问题由两个核心错误导致:
- Axios请求未指定
responseType: 'blob',默认会将响应体解析为UTF-8字符串,大体积二进制内容解析为字符串时会发生溢出截断,导致最终拿到的response.data不完整甚至为空。 - 现有代码将字符串形式的
response.data手动包装为Blob,字符串截断后生成的Blob自然就是空的。
修复步骤
1. 调整Axios请求配置
发起下载请求时必须添加responseType: 'blob'配置,让Axios直接将响应体解析为Blob对象,避免字符串截断问题:
// 下载请求示例 axios.get('/your/download/api', { responseType: 'blob', // 核心必填配置 timeout: 0, // 可选:大文件下载关闭超时限制,避免下载到一半被中断 })
2. 调整下载逻辑
修改原有代码,直接使用Axios返回的Blob对象,不需要手动二次包装:
import * as contentDisposition from 'content-disposition'; import * as downloadjs from 'downloadjs'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; import { ApiResponse } from '../api'; const defaultContentType = 'text/plain'; const defaultFilename = 'file.txt'; const downloadFile = (response: ApiResponse<Blob>, filename?: string) => { // 生成文件名 if (!filename) { const parsedContentDisposition = response.headers['content-disposition'] && contentDisposition.parse(response.headers['content-disposition']); filename = parsedContentDisposition && parsedContentDisposition.parameters ? parsedContentDisposition.parameters.filename : defaultFilename; } // 生成content type const contentType = response.headers['content-type'] ? response.headers['content-type'] : defaultContentType; // 直接用返回的Blob对象下载,不需要手动new Blob包装 downloadjs(response.data, filename, contentType); }; export const downloadFileFromStream = (filename?: string) => ( stream$: Observable<ApiResponse<Blob>>, ) => stream$.pipe(tap(response => downloadFile(response, filename)));
超大文件(>2G)优化方案
如果需要下载超过2G的文件,全量加载到内存会导致浏览器卡顿甚至崩溃,可以改用流式下载方案:
- 将Axios的
responseType设为stream,获取响应的ReadableStream对象 - 搭配流式下载工具直接将数据流写入本地磁盘,不需要全量加载到内存
常见注意事项
- 如果你封装了Axios全局拦截器,不要对Blob类型的响应做JSON序列化处理,会损坏Blob对象
- 跨域请求时需要后端在
Access-Control-Expose-Headers响应头中添加content-disposition,否则前端无法读取该头获取文件名 - 大文件下载接口建议后端关闭gzip压缩,避免浏览器无法正确判断文件大小导致下载异常
内容的提问来源于stack exchange,提问作者margorp
相关产品推荐
相关产品推荐

