同一个接口返回不同类型数据
如果 同一个接口“既可能返回数据流(如文件、blob、arraybuffer),又可能返回正常 JSON 数据”,那么 axios 无法在请求前就自动知道返回类型,你必须手动做两件事:
- 请求时设置通用接收类型(通常用
responseType: 'arraybuffer'或blob) - 收到响应后根据内容再判断是 JSON 还是文件流
下面给你最佳实践:
✅ 方案一:统一用 arraybuffer 接收,再判断是不是 JSON
这是 最推荐、最通用的方式。
请求:
js
axios.get('/api/download-or-json', {
responseType: 'arraybuffer'
})拿到数据后判断类型:
js
axios.get('/api/download-or-json', {
responseType: 'arraybuffer'
})
.then(res => {
const contentType = res.headers['content-type'];
if (contentType.includes('application/json')) {
// arraybuffer 转 json
const decoder = new TextDecoder('utf-8');
const text = decoder.decode(res.data);
const json = JSON.parse(text);
console.log('是 JSON:', json);
} else {
// 当成文件流处理
const blob = new Blob([res.data], { type: contentType });
console.log('是文件流', blob);
// 比如下载文件:
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'download';
link.click();
URL.revokeObjectURL(link.href);
}
});为什么要用 arraybuffer?
因为:
arraybuffer可以接收所有类型的数据- JSON 可以从 arraybuffer “反序列化”回来
- 文件流也能保持二进制不损坏
而用 responseType: 'json' 会导致文件流直接报错。 用 blob 也能判断,但解析 JSON 略麻烦。
✅ 方案二:用 blob + FileReader 判断 JSON / 流
也很常见:
js
axios.get('/api/download-or-json', { responseType: 'blob' })
.then(async res => {
const contentType = res.headers['content-type'];
if (contentType.includes('application/json')) {
const text = await res.data.text();
const json = JSON.parse(text);
console.log('JSON:', json);
} else {
console.log('文件流:', res.data);
}
});也可以,但 blob 转 json 时需要多一步。
❌ axios 是否可以自动处理“半 JSON 半流”的返回?
不能。
因为 responseType 必须在请求前决定。
接口如果返回:
- 文件 → binary
- JSON → text
两者不兼容,所以必须用单一类型接收后再判断。
⭐ 总结(最推荐的写法)
统一用 arraybuffer 接收 + 根据 Content-Type 判断。
js
axios.get(url, { responseType: 'arraybuffer' })
.then(res => {
const type = res.headers['content-type'];
if (type.includes('application/json')) {
const json = JSON.parse(new TextDecoder().decode(res.data));
console.log(json);
} else {
const blob = new Blob([res.data], { type });
// 当文件处理
}
});