一、概述
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) })
|
参考资料