前端服务端实现文件下载整个流程案例在实际的开发过程中,经常会遇到需要从后端下载文件的情况,特别是 Excel 文件这种常
在实际的开发过程中,经常会遇到需要从后端下载文件的情况,特别是 Excel 文件这种常见的数据存储和交换格式。本文将详细介绍如何在前端使用 fetch
请求从后端下载 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
。
四、遇到的问题及解决方法
- 响应体乱码问题:一开始,我们在浏览器中看到下载请求的响应体是一堆乱码。通过分析,我们确定这是因为后端返回的是二进制流数据,而浏览器以文本形式尝试显示导致的。为了解决这个问题,我们在后端设置了正确的响应头,指定了内容类型为 Excel 文件的 MIME 类型,并在前端将响应转换为
blob
类型进行处理。 - 跨域问题:如果前端和后端运行在不同的端口,可能会遇到跨域问题。我们可以在后端使用
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