后端返回了 xlsx 文件流,前端怎么下载处理

发布于:2025-03-26 ⋅ 阅读:(43) ⋅ 点赞:(0)

当后端返回一个 .xlsx 文件流时,前端可以通过 JavaScript 处理这个文件流并触发浏览器下载。


实现步骤

  1. 发送请求获取文件流
    使用 fetchaxios 等工具向后端发送请求,确保响应类型设置为 blob(二进制数据流)。

  2. 创建 Blob 对象
    将返回的文件流转换为 Blob 对象,这是处理二进制数据的标准方式。

  3. 生成下载链接
    使用 URL.createObjectURL 方法将 Blob 对象转换为一个临时 URL。

  4. 触发下载
    动态创建一个 <a> 标签,设置其 href 属性为生成的临时 URL,并调用 click() 方法触发下载。

  5. 清理资源
    下载完成后,使用 URL.revokeObjectURL 释放生成的临时 URL,避免内存泄漏。


使用 axios 实现

如果你使用的是 axios,可以这样实现:

import axios from 'axios';

const downloadXlsx = async () => {
  try {
    // 发送请求并获取文件流
    const response = await axios.get('/api/download-xlsx', {
      responseType: 'blob', // 确保响应类型为 blob
      headers: {
        'Authorization': 'Bearer your_token_here', // 如果需要携带认证信息
      },
    });

    // 创建 Blob 对象
    const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });

    // 创建临时 URL
    const url = window.URL.createObjectURL(blob);

    // 创建 <a> 标签并触发下载
    const a = document.createElement('a');
    a.href = url;
    a.download = 'example.xlsx'; // 设置下载文件名
    document.body.appendChild(a); // 将 <a> 添加到 DOM 中(可选)
    a.click(); // 触发点击事件

    // 清理资源
    window.URL.revokeObjectURL(url);
    a.remove(); // 移除 <a> 标签
  } catch (error) {
    console.error('下载文件时发生错误:', error.message || '未知错误');
  }
};

// 调用函数
downloadXlsx();
responseType: 'blob' 的含义
  • responseType 是 Axios 提供的一个配置选项,用于告诉 Axios 如何解析服务器返回的数据。
  • 当设置为 'blob' 时,表示你期望服务器返回的数据是一个二进制大对象(Binary Large Object,简称 Blob)。
Blob 是什么?
  • Blob 是一种数据类型,通常用来表示不可变的、原始数据的类文件对象。
  • 它可以包含文本、图像、音频、视频等二进制数据,或者混合内容。
  • 在前端开发中,Blob 常用于处理文件下载、图片预览、或者将数据保存为文件。
为什么需要 responseType: 'blob'

当从服务器请求文件(如 Excel 文件、PDF 文件、图片等)时,服务器通常会返回二进制数据。如果直接使用默认的 responseType(通常是 'json'),Axios 会尝试将响应数据解析为 JSON 格式,这会导致错误或数据损坏。

通过设置 responseType: 'blob',你可以确保 Axios 正确地将响应数据作为二进制数据处理,而不会尝试将其解析为其他格式(如 JSON 或文本)。

代码的作用
const response = await axios({
  url: '/api/download-xlsx',
  method: 'GET',
  responseType: 'blob', // 指定响应数据为 Blob 类型
});
  1. 发起 GET 请求

    • 向 /api/download-xlsx 发起一个 GET 请求,通常用于下载文件(例如 Excel 文件)。
  2. 指定响应类型

    • 设置 responseType: 'blob',告诉 Axios 将服务器返回的数据解析为 Blob 对象。
  3. 处理响应数据

    • 返回的 response.data 将是一个 Blob 对象,代表下载的文件内容。

使用 fetch 实现

const downloadXlsx = async () => {
  try {
    // 发送请求并获取文件流
    const response = await fetch('/api/download-xlsx', {
      method: 'GET',
      headers: {
        'Authorization': 'Bearer your_token_here', // 如果需要携带认证信息
      },
    });

    // 检查响应是否成功
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }

    // 获取 blob 数据
    const blob = await response.blob();

    // 创建临时 URL
    const url = window.URL.createObjectURL(blob);

    // 创建 <a> 标签并触发下载
    const a = document.createElement('a');
    a.href = url;
    a.download = 'example.xlsx'; // 设置下载文件名
    document.body.appendChild(a); // 将 <a> 添加到 DOM 中(可选)
    a.click(); // 触发点击事件

    // 清理资源
    window.URL.revokeObjectURL(url);
    a.remove(); // 移除 <a> 标签
  } catch (error) {
    console.error('下载文件时发生错误:', error.message || '未知错误');
  }
};

// 调用函数
downloadXlsx();
1. 定义异步函数
javascript
深色版本
const downloadXlsx = async () => {
  • async 关键字表示这是一个异步函数。
  • 异步函数允许使用 await 来等待异步操作(如网络请求)完成。

2. 发起 HTTP 请求
const response = await fetch('/api/download-xlsx', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer your_token_here', // 如果需要携带认证信息
  },
});
  • 使用 fetch 发起一个 GET 请求到 /api/download-xlsx

  • headers 部分用于设置请求头:

    • 'Authorization' 是一个常见的请求头字段,用于传递用户的身份验证信息(如 JWT Token)。
    • 如果 API 不需要认证,可以省略 headers

3. 检查响应状态
if (!response.ok) {
  throw new Error(`HTTP error! Status: ${response.status}`);
}
  • response.ok 是一个布尔值,表示 HTTP 响应的状态码是否在 200-299 范围内。
  • 如果响应失败(如 404 或 500 错误),会抛出一个错误,并终止后续代码执行。
  • 抛出的错误会被 catch 块捕获。

4. 获取 Blob 数据
const blob = await response.blob();
  • response.blob()  将响应数据解析为一个 Blob 对象。
  • Blob 是一种二进制数据类型,通常用来表示文件内容。
  • await 确保在继续执行后续代码之前,blob 数据已经被完全加载。

5. 创建临时 URL
const url = window.URL.createObjectURL(blob);
  • window.URL.createObjectURL(blob)  创建一个指向 Blob 的临时 URL。
  • 这个 URL 可以被用作 <a> 标签的 href 属性,从而触发文件下载。

6. 创建 <a> 标签并触发下载
const a = document.createElement('a');
a.href = url;
a.download = 'example.xlsx'; // 设置下载文件名
document.body.appendChild(a); // 将 <a> 添加到 DOM 中(可选)
a.click(); // 触发点击事件
  • 创建 <a> 标签

    • 使用 document.createElement('a') 动态创建一个 <a> 元素。
  • 设置 <a> 标签属性

    • href:设置为前面生成的临时 URL。
    • download:指定下载文件的名称(如 example.xlsx)。
  • 添加到 DOM 并触发点击

    • 将 <a> 标签添加到文档中(虽然不是必须,但某些浏览器可能需要这样做)。
    • 使用 a.click() 模拟用户点击,从而触发文件下载。

7. 清理资源
window.URL.revokeObjectURL(url);
a.remove();
  • 释放临时 URL

    • 使用 window.URL.revokeObjectURL(url) 释放前面创建的临时 URL,避免内存泄漏。
  • 移除 <a> 标签

    • 使用 a.remove() 从 DOM 中移除 <a> 标签,保持页面整洁。

8. 错误处理
} catch (error) {
  console.error('下载文件时发生错误:', error.message || '未知错误');
}
  • catch 块 用于捕获和处理可能出现的错误。
  • 如果在 try 块中的任何一步发生错误(如网络问题、API 返回错误等),都会进入 catch 块。
  • 使用 console.error 打印错误信息,方便调试。

9. 调用函数
downloadXlsx();
  • 最后调用 downloadXlsx 函数,触发整个文件下载流程。
适用场景
  • 下载动态生成的文件(如 Excel 表格、PDF 文档等)。
  • 需要通过 API 获取文件内容并提供给用户下载的场景。
注意事项
  1. 跨域问题

    • 如果 API 存在跨域限制,需要确保服务器配置了正确的 CORS(跨域资源共享)策略。
  2. 大文件下载

    • 对于非常大的文件,可能需要考虑分块下载或流式处理,以避免内存占用过高。
  3. 浏览器兼容性

    • fetch 和 Blob 在现代浏览器中广泛支持,但在一些老旧浏览器中可能需要使用 XMLHttpRequest 替代。

关键点说明

  1. 设置正确的 MIME 类型

    • .xlsx 文件的 MIME 类型是 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    • 如果后端未正确设置 MIME 类型,前端可以通过 Blob 的第二个参数手动指定。
  2. 动态文件名

    • 如果后端在响应头中提供了文件名(例如通过 Content-Disposition),可以通过解析响应头来动态设置文件名。
    • 示例:
      const contentDisposition = response.headers['content-disposition'];
      let fileName = 'example.xlsx';
      if (contentDisposition && contentDisposition.includes('filename=')) {
        fileName = contentDisposition.split('filename=')[1].split(';')[0];
      }
      
  3. 错误处理

    • 在实际开发中,务必对请求错误进行处理,例如检查 HTTP 状态码是否为 200,或者捕获网络异常。
  4. 兼容性

    • 上述方法适用于现代浏览器(如 Chrome、Firefox、Edge、Safari)。如果需要支持旧版浏览器,可能需要引入 FileSaver.js 库。

使用 FileSaver.js 简化操作

如果你希望简化文件下载逻辑,可以使用第三方库 file-saver。安装后,只需几行代码即可完成下载。

安装
npm install file-saver
使用示例
import { saveAs } from 'file-saver';
import axios from 'axios';

const downloadXlsx = async () => {
  try {
    const response = await axios({
      url: '/api/download-xlsx',
      method: 'GET',
      responseType: 'blob',
    });

    // 使用 FileSaver.js 保存文件
    saveAs(response.data, 'example.xlsx');
  } catch (error) {
    console.error('下载失败:', error);
  }
};

// 调用函数
downloadXlsx();

总结

  • 核心步骤:获取文件流 -> 转换为 Blob -> 创建临时 URL -> 触发下载 -> 清理资源。
  • 推荐工具fetchaxios 可以轻松获取文件流,FileSaver.js 可以进一步简化代码。
  • 注意事项:确保后端返回的文件流格式正确,前端设置合适的 MIME 类型和文件名。

axios 处理

try {
    const response = await axios({
      url: '/api/download-xlsx',
      method: 'GET',
      responseType: 'blob', // 一定要注意请求时加此方法
    });


getExportListApi(exportCarryData).then((res) => {
      // 创建一个a标签
      const link = document.createElement('a');
      const url = window.URL.create0bjectURL(new Blob([res.data])); 
      link.href = url;
      link.setAttribute('download', exportfile);
       
      document.body.appendChild(link); 
      link.click();
      // 销毁a标签
      document.body.removeChild(link); window.URL.revoke0bjectURL(url);

      message.success('导出成功!');
    });