问题描述
在实现需求:批量下载的时候,返回的数据类型设置为blob
$http({
method: 'post',
url: dataurl,
data: bodyParam,
headers: { 'Content-Type': 'application/jsons', },
responseType: 'blob'
})
然后在项目运行的时候,报错:
TypeError: Failed to execute ‘readAsText‘ on ‘FileReader‘: parameter 1 is not of type ‘Blob‘.
解决方法
这个问题在总结的时候,当时忘记了,现在才像起来,然后之前的错误的代码,忘记保存了,懒得去找,现在这个改过的代码,给大家参考一下。
$http({
method: 'post',
url: dataurl,
data: bodyParam,
headers: { 'Content-Type': 'application/jsons', },
responseType: 'blob'
}).then(function successCallback(response) {
noty && noty.close()
console.log("response", response)
var blob = new Blob([response.data]);
let data = response.data;
// 有可能会下载失败,比如返回{retcode:500}
//但设置了responseType: 'blob',会把data强制转为blob,导致下载undefined.excel(后缀取决于文件类型,这里只是举例)
// 解决:将已转为blob类型的data转回json格式,判断是否下载成功
const r = new FileReader()
r.onload = function () {
// 如果JSON.parse(this.result)不报错,说明this.result是json字符串,则可以推测是下载报错情况下返回的对象,类似于{retcode:500}
// 如果JSON.parse(this.result)报错,说明是下载成功,返回的二进制流,则进入catch进行后续处理
try {
const resData = JSON.parse(this.result)// this.result为FileReader获取blob数据转换为json后的数据,即后台返回的原始数据
console.log("resData", resData)
$mdDialog.hide({
comfirmStatus: true
});
notyService.error({
text: "下载失败!" + resData.errmsg
});
// 如果执行到这里,说明下载报错了,进行后续处理
} catch (err) {
if (response.data.type === 'application/octet-stream') {
var blobUrl = window.URL.createObjectURL(blob)
console.log(blobUrl);
var tempLink = document.createElement('a');
//初始化事件对象
tempLink.style.display = 'none'
tempLink.href = blobUrl
tempLink.setAttribute('download', 'config_pkg' + formatDate() + '.tgz')
document.body.appendChild(tempLink);
let e = document.createEvent('MouseEvents') // 创建鼠标事件对象
e.initEvent('click', false, false) //
//tempLink.click();
//用完即删
document.body.removeChild(tempLink);
$mdDialog.hide({
comfirmStatus: true
});
notyService.success({
text: "下载成功"
});
tempLink.dispatchEvent(e)
window.URL.revokeObjectURL(blobUrl);
} else {
$mdDialog.hide({
comfirmStatus: true
});
notyService.error({
text: "下载失败:返回的文件类型不支持下载"
});
}
}
}
r.readAsText(data) // FileReader的API
}).catch(res => {
console.log(res)
});