场景:项目中请求图片或者下载文件一般情况下都是接口返回url或者接口本身就是一个get请求访问接口直接下载。但是在某些情况下,接口会返回一个二进制文件流,在控制台打印或者network的preview中就是一串看不懂的字符串(下图)
第一次遇到的时候也是一脸迷茫,就顺着惯性思维总觉得接口返回的不对。但其实只是自己技术有限,没有接触到而已。这就是接口返回的文件的二进制流,通过js的Blob对象是可以转成文件下载下来的。
二进制流转图片:如果接口返回的是个图片,前端需求是展示这个图片,可以直接将api放到img标签的src中,和普通ajax请求的接口一样,这样在浏览器network中可以看到这个图片和请求一样,不过类型成了img类型的。
二进制流下载:借助blob对象,直接贴代码
let xhr = new XMLHttpRequest()
let fileName = 'file.docx' // 文件名称
xhr.open('GET', Api, true)
xhr.responseType = 'arraybuffer'
xhr.setRequestHeader(token, 'xxxxx') // 请求头中的验证信息等(如果有)
xhr.onload = function() {
if (this.status === 200) {
let type = xhr.getResponseHeader('Content-Type')
let blob = new Blob([this.response], {type: type})
if (typeof window.navigator.msSaveBlob !== 'undefined') {
/*
* IE workaround for "HTML7007: One or more blob URLs were revoked by closing
* the blob for which they were created. These URLs will no longer resolve as
* the data backing the URL has been freed."
*/
window.navigator.msSaveBlob(blob, fileName)
} else {
let URL = window.URL || window.webkitURL
let objectUrl = URL.createObjectURL(blob)
if (fileName) {
var a = document.createElement('a')
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location = objectUrl
} else {
a.href = objectUrl
a.download = fileName
document.body.appendChild(a)
a.click()
a.remove()
}
} else {
window.location = objectUrl
}
}
}
}
xhr.send()
09/12更新:
在接口做验证的时候,如果验证失败,接口返回json信息,但是由于设置了responseType='arraybuffer',这时候this.response将不再是json字符串,而是ArrayBuffer对象,要处理它来将后台返回的信息展示出来。
let uint8 = new Uint8Array(this.response) // 提取uint8Array
let resToString = decodeURIComponent(escape((String.fromCharCode(...uint8)))) // 解决乱码
得到的resToString就是后台返回的json字符串了。
只通过String.fromCharCode会出现中文乱码的情况