axios下载msword文件损坏
场景
项目中请求后端接口下载一个docx文件。
Response如下:


这时首先想到的是后端返回了二进制流,需要将流转换为Blob,生成downloadUrl,使用a标签下载。
Ctrl V 百度的代码:
axios({
url: 'http://localhost:5000/download',
method: 'POST',
data: {
//...
},
responseType: 'blob', // 设置服务器响应的数据类型(必选)
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.download = 'file.docx';
link.click();
});
然后愉快的测试,word下载成功。
继续打开文件,报错:很抱歉,无法打开xxx.docx,因为内容有问题。

内容有毛问题?点击确定:Word 在 xxx.docx 中发现无法读取的内容,是否恢复此文档的内容?如果您信任此文档的来源,请点击“是”

点击“是”还是无法打开,一定是后端的问题,过去撕逼。
然后被打脸:后端使用API文档工具测试,下载的文件可以正常打开。
继续回到座位百度,答案基本一样,观察细节尝试各种办法(可以直接跳转到最后查看成功的办法):
尝试办法1:
在创建Blob时指定type:
let blob = new Blob([response.data], {type: 'application/msword'}) // 不行
let blob = new Blob([response.data], {type: 'application/octet-stream'}) // 不行
尝试方法2:
把正常的和不正常的docx文件后缀改为txt对比,发现虽然开头都是PK,但是我下载的文件中有大量的�。
而后端下载的文件内容虽然也看不懂(鱀咯暜==|eg?~€澐Y}跿憓之类的),但是没有�。
难道是编码问题?
再看看F12的response,返回的本来就是带�的,忍住找后端的冲动。
开始从编码着手,可是项目默认请求的Content-Type就是 UTF-8 啊。

先试着请求时手动设置 Content-Type ,并没有解决。
axios({
url: 'http://localhost:5000/download',
method: 'POST',
data: {
//...
},
headers: {
'content-type': 'application/json;charset=UTF-8'
},
responseType: 'blob', // 设置服务器响应的数据类型(必选)
}).then((response) => {
//...
});
尝试方法3:
设置 responseType: 'arraybuffer',并没有解决
尝试方法4:
然后又百度到用 Base64 转码,尝试了,并没有解决。
尝试方法5(成功):
再次console打印接口返回的内容:

responseType: 'blob'设置成功了呀。
终于百度到一个靠谱的大神,多亏他回答问题是作了额外的说明(感激不尽)。
大神原话:
可以明显的看到,返回的response在的data 是一个blob Object。
createObjectURL 函数,接受的参数是blob 类型或者是File 类型。
所以说,我想创建的URL 对象只需要 如下代码
let url = URL.createObjectURL(response.data)
因为response.data 已经是一个blob Object 了,完全不需要再像let url = window.URL.createObjectURL(new Blob([response.data]))载入
百度到的回答,都是用new Blob创建一个Blob,所以我完全没质疑过这个使用,并且没有查看过createObjectURL的使用方法。
于是调整代码,再次测试,word可以正常打开了。
axios({
url: 'http://localhost:5000/download',
method: 'POST',
data: {
//...
},
responseType: 'blob', // 设置服务器响应的数据类型(必选)
}).then((response) => {
const url = window.URL.createObjectURL(new Blob(response.data)); // 调整了这里
const link = document.createElement('a');
link.href = url;
link.download = 'file.docx';
link.click();
});
其他坑
有时由于封装 Axios 造成传参不规范,例如本项目中封装的请求,就把 responseType 包裹在 headers 中,导致开发人员工具中Request Header 中虽然显示了 responseType: blob 但是并没有没生效。

排查这个问题浪费了点时间,最终还是查看打印的 Axios 返回结果的 request.responseType为空才发现。

网上也有说使用mock的某些场景会把 responseType 默认修改为''
本文详细记录了使用Axios下载MSWord文件时遇到的文件损坏问题及解决方案。通过调整createObjectURL的使用方式,避免了不必要的Blob创建过程,成功解决了文件无法正常打开的难题。
1742

被折叠的 条评论
为什么被折叠?



