likes
comments
collection
share

前端服务端实现文件下载整个流程案例在实际的开发过程中,经常会遇到需要从后端下载文件的情况,特别是 Excel 文件这种常

作者站长头像
站长
· 阅读数 39

在实际的开发过程中,经常会遇到需要从后端下载文件的情况,特别是 Excel 文件这种常见的数据存储和交换格式。本文将详细介绍如何在前端使用 fetch 请求从后端下载 Excel 文件,并处理后端返回的二进制流响应。

一、问题背景

在项目开发中,我们需要实现一个功能,让用户能够从前端界面触发下载 Excel 文件的操作。后端提供了一个下载接口,但是在实际测试过程中,我们发现当请求这个接口时,在浏览器的标签页中看到响应体是一堆乱码。经过分析,我们确定这是因为后端返回的是二进制流数据,而浏览器以文本形式尝试显示导致的。

前端服务端实现文件下载整个流程案例在实际的开发过程中,经常会遇到需要从后端下载文件的情况,特别是 Excel 文件这种常

二、后端实现

我们使用 Node.js 和 Express 框架来搭建后端服务。以下是关键的代码部分:

const express = require('express');
const app = express();
const fs = require('fs');

app.get('/download', (req, res) => {
  // 假设要下载的文件是一个 Excel 文件,路径为项目根目录下的 your-excel-file.xlsx
  const filePath = './your-excel-file.xlsx';
  const fileStream = fs.createReadStream(filePath);
  // 设置响应头,指定内容类型为 Excel 文件的 MIME 类型
  res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  // 设置下载时的文件名
  res.setHeader('Content-Disposition', 'attachment; filename=your-excel-file.xlsx');
  // 使用管道将文件流传输到响应中
  fileStream.pipe(res);
});

const port = 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

在上述代码中,当接收到前端的下载请求时,后端使用 fs.createReadStream 创建文件流,并将文件流通过管道传输到响应中。同时,设置了适当的 Content-Type 和 Content-Disposition 响应头,确保浏览器能够正确处理下载请求。

三、前端实现

前端使用 fetch 来发起下载请求,并处理响应的二进制流数据以触发文件下载。以下是前端代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button onclick="downloadFile()">下载 Excel 文件</button>
  <script>
    function downloadFile() {
      fetch('/download', {
          method: 'GET',
          headers: {}
        })
      .then(response => {
          if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
          }
          return response.blob();
        })
      .then(blob => {
          const url = window.URL.createObjectURL(blob);
          const link = document.createElement('a');
          link.href = url;
          link.setAttribute('download', 'downloaded-excel-file.xlsx');
          document.body.appendChild(link);
          link.click();
        })
      .catch(error => {
          console.error('下载失败:', error);
        });
    /* axios写法 */
      function downloadFile() {
         axios.get('/download', {
           responseType: 'blob'
         })
        .then(response => {
           const url = window.URL.createObjectURL(new Blob([response.data]));
           const link = document.createElement('a');
           link.href = url;
           link.setAttribute('download', 'downloaded-file.txt');
           document.body.appendChild(link);
           link.click();
         })
        .catch(error => {
           console.error('下载失败:', error);
         });
       }
    }
  </script>
</body>

</html>

当用户点击页面上的按钮时,会触发 downloadFile 函数。这个函数使用 fetch 向后端的 /download 接口发送请求。当接收到响应时,将其转换为 blob 类型,然后创建一个临时的下载链接并触发下载,设置下载的文件名为 downloaded-excel-file.xlsx

四、遇到的问题及解决方法

  1. 响应体乱码问题:一开始,我们在浏览器中看到下载请求的响应体是一堆乱码。通过分析,我们确定这是因为后端返回的是二进制流数据,而浏览器以文本形式尝试显示导致的。为了解决这个问题,我们在后端设置了正确的响应头,指定了内容类型为 Excel 文件的 MIME 类型,并在前端将响应转换为 blob 类型进行处理。
  2. 跨域问题:如果前端和后端运行在不同的端口,可能会遇到跨域问题。我们可以在后端使用 cors 中间件或者设置响应头来解决跨域问题。例如:
   const cors = require('cors');
   app.use(cors());

或者在后端设置响应头:

   app.use((req, res, next) => {
     res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8001');
     res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
     res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
     if (req.method === 'OPTIONS') {
       res.sendStatus(200);
     } else {
       next();
     }
   });

如果使用前端框架,如 Vue 或 React,也可以在框架的配置文件中设置代理来解决跨域问题。

五、总结

通过本次技术实践,我们成功实现了从前端请求后端下载 Excel 文件的功能,并处理了后端返回的二进制流响应。在这个过程中,我们遇到了一些问题,如响应体乱码和跨域问题,但通过分析问题的原因并采取相应的解决方法,我们顺利地解决了这些问题。这次实践不仅加深了我们对前端和后端数据交互的理解,也为今后处理类似的文件下载需求提供了宝贵的经验。 希望这篇博客能够帮助到其他遇到类似问题的开发者,让大家在处理前端下载文件和处理二进制流响应时更加得心应手。

转载自:https://juejin.cn/post/7408821833552543770
评论
请登录