之前开发的项目中都是单个下载文件,可以利用的方法有很多,例如:
1、FileReader实例的readAsDataURL()方法
2、window.URL对象的createObjectURL()方法(需要注意下载完成后利用revokeObjectURL()方法释放内存)
3、直接window.open
且基本都是通过GET请求来获取,然后这次碰到情况跟以前有点不一样。
第一这次是通过post请求来获取文件流;第二需要下载的是zip类型的文件(因为是批量下载),这就让我有点摸不着头脑,然后经过我花费了大量时间翻阅资料,然后踩了无数的坑,最后给我找到了解决方法,特写个文章记录记录。
首先看解决方法(这里用的是原生js):
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/json");
xhr.responseType = 'blob';
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
let res = xhr.response; //不是responseText。
let blob = new Blob([res]);
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = blobUrl;
a.download = "批量下载.zip";
a.click();
URL.revokeObjectURL(blobUrl); // 释放内存
setMoreAlertVisible(false);
//另一种读取方法
// var reader = new FileReader(); // 是一个对象,其唯一目的是从 Blob(因此也从 File)
//对象中读取数据。
// reader.readAsDataURL(blob); // 转换为base64,可以直接放入a标签href
// reader.onload = (e) => {
// // 转换完成,创建一个a标签用于下载
// var a = document.createElement("a");
// a.download = "批量下载.zip";
// a.href = e.target.result;
// document.body.appendChild(a);
// a.click();
// document.body.removeChild(a);
// };
}
}
xhr.send(JSON.stringify(obj));
需要注意到的地方是在设置了responseType之后,读取响应内容用的是xhr.response,而不是xhr.responseText,其次就是需要后台设置响应头Content-type: application/octet-stream
深入了解:
(1)这里需要牵涉到一个属性responseType,这里贴个图解释一下:
然后如何去设置它呢?
1、原生js在使用XMLHttpRequest对象时,可以直接通过xhr.responseType = "blob"设置
2、使用axios时,可以直接在参数对象里写入:responseType: "blob"
3、使用jquery时,就不能直接设置,需要借助xhrFields属性,设置xhrFieIds: {responseType: "blob"}
(2)Blob对象(构造函数返回一个新的 Blob 对象。 blob的内容由参数数组中给出的值的串联组成)
基本用法:var blob = new Blob(arr, object);
参数说明:
arr: 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings会被编码为UTF-8。
object: 是一个可选的BlobPropertyBag
字典,它可能会指定如下两个属性:
1、type: 默认值为 ""
,它代表了将会被放入到blob中的数组内容的MIME类型
2、endings: 默认值为"transparent"
,用于指定包含行结束符\n
的字符串如何被写入。 它是以下两个值中的一个: "native"
,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent"
,代表会保持blob中保存的结束符不变。
详细用法跳转:Blob() - Web API 接口参考 | MDN