业务场景
今天遇到一个问题,后端给了一个接口,要用POST请求这个接口,后端会返回 Content-Type: application/octet-stream;charset=UTF-8
类型的数据,是一个xls文件,post的请求负载必须是 Content-Type: application/json
,所以我就选择了用jq.ajax + blob来下载这个Excel文件。
实现代码如下:
$.ajax({
type: "POST",
url: url,
data: JSON.stringify(data),
dataType: 'binary', // ?
xhrFields: { responseType: "blob" }, //?
contentType: "application/json",
success: function (res) {
let blob = new Blob([res])
let da = document.createElement('a')
da.href = URL.createObjectURL(blob);
da.setAttribute("download","data.xls");
da.click();
URL.revokeObjectURL(da.href);
},complete: function(){
console.log(...arguments)
}
});
其中两行代码让我很困惑,就是
dataType: 'binary', // ?
xhrFields: { responseType: "blob" }, //?
去掉这两行的任一一个,complete回调时都会提示parsererror,所以想请教一下,这两行代码究竟是起了什么样的作用,为什么缺一不可?
jQuery.ajax的文档下面应该已经解释很清楚了,
xhrFields: 接受一个key-value对象,透传给原生的XHR。比如这里的responseType,就可以从XHR的文档上查到相关解释XMLHttpRequest/responseType,指定响应的数据类型,默认类型 DOMString,与设置为 text 相同。这里是返回的二进制文件,所以需要指定成blob。
dataType: (default: 自动识别(xml, json, script, or html)),所以对于返回二进制流类型的数据,这里就需要特别设置一下,无法自动识别
另外对于这类下载场景,通常用window.open,或者直接设置a标签链接,通过get请求触发浏览器下载,没必要自己调用ajax去请求再触发下载