Skip to content

同一个接口返回不同类型数据

如果 同一个接口“既可能返回数据流(如文件、blob、arraybuffer),又可能返回正常 JSON 数据”,那么 axios 无法在请求前就自动知道返回类型,你必须手动做两件事:

  1. 请求时设置通用接收类型(通常用 responseType: 'arraybuffer'blob
  2. 收到响应后根据内容再判断是 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 });
      // 当文件处理
    }
  });