技术实录 | 你是否有过axios下载的文件打不开的经历?
2023-10-31 21:48:56
现象
在使用axios库下载文件时,开发者经常会遇到这样的困惑:明明下载成功了,却无法打开。这时,仔细检查控制台,可能会发现错误信息中提示“Response has no content”或“Invalid file format”。
问题分析
造成此问题的根源在于axios库默认使用XMLHttpRequest对象来发送请求,而XMLHttpRequest对象有一个responseType属性,用来指定服务器响应的数据类型。当responseType设置为“arraybuffer”时,浏览器会将服务器响应的二进制数据存储在一个ArrayBuffer对象中,从而实现文件的下载。
然而,如果在开发过程中使用了mock.js这样的模拟数据库,则可能会导致这个问题。mock.js会重置XMLHttpRequest对象的responseType属性,使其变更为“json”。这将导致服务器响应的二进制数据被解析为JSON格式,从而导致文件损坏,无法打开。
解决方案
解决这个问题的步骤如下:
-
在使用mock.js时,需要在调用mock.setup()方法之前,对XMLHttpRequest对象的responseType属性进行备份,并在mock.setup()方法调用之后将其还原。
-
在使用axios下载文件时,需要明确指定responseType属性的值为“arraybuffer”,以确保服务器响应的二进制数据能够正确存储在ArrayBuffer对象中。
-
如果在使用axios下载文件时,遇到了“Response has no content”或“Invalid file format”等错误信息,则可以考虑是否使用了mock.js,并检查XMLHttpRequest对象的responseType属性是否被重置。
代码示例
// 备份XMLHttpRequest对象的responseType属性
const originalResponseType = XMLHttpRequest.prototype.responseType;
// 设置mock.js
mock.setup({
timeout: 1000
});
// 使用axios下载文件
axios.get('/file.txt', {
responseType: 'arraybuffer'
})
.then((response) => {
// 将文件内容保存到本地
const blob = new Blob([response.data], {type: 'text/plain'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'file.txt';
a.click();
URL.revokeObjectURL(url);
})
.catch((error) => {
// 处理错误
console.error(error);
});
// 还原XMLHttpRequest对象的responseType属性
XMLHttpRequest.prototype.responseType = originalResponseType;
总结
通过axios下载文件时,如果遇到文件无法打开的问题,可以考虑是否使用了mock.js,并检查XMLHttpRequest对象的responseType属性是否被重置。通过备份和还原responseType属性,可以确保axios能够正确下载文件。