axios下载msword文件损坏

本文详细记录了使用Axios下载MSWord文件时遇到的文件损坏问题及解决方案。通过调整createObjectURL的使用方式,避免了不必要的Blob创建过程,成功解决了文件无法正常打开的难题。

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 默认修改为''

大神出处

papersnake 的回答

### 问题背景 从 `http://192.168.0.147:8080/score/exportScoreId?scoreId=13` 下载的文档流在转换后无法正确打开,特别是在处理 `.docx`(Word 文档)文件时。该接口返回的是二进制文件流,而非 Base64 编码或静态链接。因此,前端必须以二进制方式接收并正确解析响应内容,否则会导致文件损坏或格式错误。 --- ### 常见问题原因分析 - **未设置正确的响应类型**:若未指定 `responseType: 'blob'`,浏览器会将响应内容解析为文本格式,导致文件结构破坏。 - **文件名编码不一致**:如果后端使用非 UTF-8 编码返回文件名,前端可能无法正确识别中文或其他特殊字符,进而影响文件保存和后续打开操作。 - **MIME 类型配置不当**:若响应头中 `Content-Type` 不是 `application/vnd.openxmlformats-officedocument.wordprocessingml.document`,浏览器可能无法识别 Word 文件格式。 - **文件流不完整**:后端未正确读取或写入文件流可能导致响应数据截断,最终下载文件不完整。 --- ### 解决方案 #### 设置请求配置以接收二进制流 确保使用 `axios` 或其他 HTTP 客户端时,设置 `responseType: 'blob'`,以便正确接收原始二进制数据。 ```javascript import axios from 'axios'; export default { methods: { downloadWordDocument() { axios.get('http://192.168.0.147:8080/score/exportScoreId', { params: { scoreId: 13 }, responseType: 'blob' }).then(response => { const contentDisposition = response.headers['content-disposition']; let fileName = 'document.docx'; if (contentDisposition) { const fileNameMatch = contentDisposition.match(/filename="?([^"]+)"?/); if (fileNameMatch.length > 1) { fileName = decodeURIComponent(fileNameMatch[1]); } } const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', fileName); document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(url); }).catch(error => { console.error('Word 文档下载失败:', error); }); } } } ``` 上述代码通过创建临时 URL 并触发 `<a>` 标签的下载行为,实现文件流的正确保存。 --- #### 处理文件名编码问题 后端应确保文件名使用 UTF-8 编码,并在响应头中进行 ISO-8859-1 转义。例如,在 Java 中可采用以下方式: ```java String encodedFileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1"); response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\""); ``` 前端则使用 `decodeURIComponent` 对文件名进行解码,以支持中文等特殊字符显示。 --- #### 验证文件完整性与 MIME 类型 - 确保响应头中的 `Content-Type` 为 `application/vnd.openxmlformats-officedocument.wordprocessingml.document`。 - 检查文件扩展名是否为 `.docx`,避免因扩展名错误导致系统无法识别。 - 使用工具如 `file`(Linux)或 `Hex Editor` 检查文件头信息,确认其是否符合 Office Open XML 格式。 现在下载的word文档,打不开,因为内容有问题 ---
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值