一、概述
AJAX 请求服务器可能返回不同的数据格式,比如返回文件或 JSON 格式————当文件由于某些原因不可下载时返回 JSON 格式。
二、问题
Axios 的核心还是使用的是 XMLHttpRequest 。可以设置 XMLHttpRequest 对象的 responseType 属性以改变从服务器端获取的预期响应。可接受的值为空字符串(默认)、arraybuffer、blob、json 或 text。XMLHttpRequest 对象的 response 属性依赖于 responseType,数据类型可能是 ArrayBuffer, Blob, Document, JSON 或 string。
三、解决方案
1. 服务端
当服务器可能返回文件或 JSON 时,Content-Type 分别设置为 application/octet-stream 或 application/json。
如果返回文件的 Content-Type 不为 application/octet-stream,则客户端在使用 js-file-download 时要设置成相同的。
2. 客户端
Axios 发送请求指定为 responseType 为 arraybuffer,如果发现 Response 的 Content-Type 为 application/json,则先将返回的数据转换成字符串,然后再转换为 JSON 。
Axios 发送请求不要指定 responseType 为 blob,因为没有方法同步地将 blob 转换为字符串或 JSON 。
Axios response interceptor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| const SuccessCode = 200 const httpClient = axios.create()
httpClient.interceptors.response.use( response => { if (response.headers['content-type'].indexOf('json') === -1) { return response }
let json if (response.request.responseType === 'arraybuffer' && response.data.toString() === '[object ArrayBuffer]') { const text = Buffer.from(response.data).toString('utf8') console.log(text) json = JSON.parse(text) } else { json = response.data }
if (json && json.url) { top.location = json.url } else if (json && json.code !== SuccessCode) { console.log(json) return Promise.reject(new Error(json.message)) } return response }, error => { return Promise.reject(error) } )
|
使用:
1 2 3 4 5 6 7 8 9 10 11
| const fileDownload = require('js-file-download')
httpClient.post(url, params, { responseType: 'arraybuffer' }).then(response => { fileDownload(response.data, 'test.xlsx') }, error => { console.log(error.message) })
|
参考资料