返回

难!axios下载文件,如何区分后端二进制与json响应?

Android

识别 Vue Axios 文件下载中的 JSON 错误响应

引言

在 Vue 项目中使用 Axios 下载文件时,responseType:blob 选项是必不可少的,但它可能会带来意想不到的麻烦。本文将深入探讨如何处理后端服务器返回 JSON 格式错误信息的情况,并提供一个优雅的解决方案。

Blob 响应的麻烦

当后端服务器一切顺利,正常返回二进制数据时,使用 responseType:blob 非常有效。然而,如果服务器出错并以 JSON 格式返回错误信息,Axios 会强制将数据转换为 Blob,这会导致 JSON 响应无法正常解析。

FileReader 的妙用

为了解决这个问题,我们需要一个能够处理二进制数据的异步读取工具——FileReader 对象。FileReader 提供了两种读取文件内容的方法:

  • readAsDataURL(file):将文件内容读入 data:url 字符串。
  • readAsBinaryString(file):逐字节读取文件内容,返回二进制字符串。

在 Axios 的 then() 方法中,我们可以使用 FileReader 对象来处理响应数据。如果响应数据的 Content-Type 是 "application/json",则很可能是后端服务器返回了 JSON 格式的错误信息。此时,我们需要使用 FileReader.readAsText() 方法读取响应数据,并将其转换为 JSON 对象。

代码示例

axios.get('api/download', {responseType: 'blob'}).then((response) => {
  if (response.headers['Content-Type'] === 'application/json') {
    const reader = new FileReader();
    reader.onload = () => {
      const data = JSON.parse(reader.result);
      console.log(data);
    };
    reader.readAsText(response.data);
  } else {
    // 文件下载
    const url = window.URL.createObjectURL(response.data);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'file.txt';
    a.click();
    window.URL.revokeObjectURL(url);
  }
});

进一步的改进

虽然这个解决方案可以解决 JSON 错误响应的问题,但它仍然存在一些局限性。例如,它只能处理文本格式的错误消息。如果错误消息包含二进制数据,则需要进一步的处理。

结论

本文介绍了一种处理 Vue Axios 文件下载中的 JSON 错误响应的方法,利用 FileReader 对象来区分二进制和 JSON 响应。虽然这种方法并不完美,但它为开发者提供了一个可靠的解决方案,使他们能够优雅地处理错误场景。

常见问题解答

  1. 为什么使用 FileReader 而不是直接将响应数据解析为 JSON?
    • Axios 会强制将所有 Blob 响应转换为二进制数据,从而覆盖响应数据的实际内容类型。FileReader 允许我们在读取之前检查响应数据的实际内容类型,从而让我们能够区分二进制和 JSON 响应。
  2. readAsText() 方法和 readAsDataURL() 方法有什么区别?
    • readAsText() 将文件内容读入字符串,而 readAsDataURL() 将文件内容读入 data:url 字符串,它包含文件内容的 base64 编码表示。
  3. 如何处理二进制错误消息?
    • 如果错误消息包含二进制数据,可以使用 readAsArrayBuffer() 方法来读取它,并使用 Buffer 类来对其进行处理。
  4. 是否还有其他处理 JSON 错误响应的方法?
    • 可以使用自定义 Axios 插件或后端代码修改来更改 Axios 对 Blob 响应的默认处理方式。
  5. 是否存在更高级别的库来处理此问题?
    • 是的,存在诸如 axios-download-manager 之类的库,它们提供了处理 Axios 文件下载的更全面的解决方案,包括错误响应处理。