文件下载
在很多场景下,我们需要导出文件,例如导出 Excel 文件,导出 Word 文件,导出 PDF 文件等等。当我们需要导出功能时,我们只需要给导出按钮配置一个点击事件,通过事件流找到请求模块,选择文件下载节点即可。
文件下载要求配置第三方API接口,第三方接口无论是基于什么语言开发,都必须返回一个二进制数据流给前端,才能实现下载或导出功能。
Java 示例
java
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@WebServlet("/download-excel")
public class ExcelDownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建 Excel 工作簿和工作表
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Sheet1");
// 2. 添加表头
Row headerRow = sheet.createRow(0);
String[] headers = {"姓名", "年龄", "城市"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
}
// 3. 添加数据行
String[][] data = {
{"张三", "28", "北京"},
{"李四", "32", "上海"},
{"王五", "25", "广州"}
};
for (int i = 0; i < data.length; i++) {
Row row = sheet.createRow(i + 1);
for (int j = 0; j < data[i].length; j++) {
row.createCell(j).setCellValue(data[i][j]);
}
}
// 4. 写入到 ByteArrayOutputStream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
workbook.write(bos);
byte[] excelBytes = bos.toByteArray();
// 5. 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=\\"example.xlsx\\"");
response.setContentLength(excelBytes.length);
// 6. 写入到响应输出流
try (OutputStream out = response.getOutputStream()) {
out.write(excelBytes);
out.flush();
}
// 7. 关闭资源
bos.close();
workbook.close();
}
}Node.js 示例
javascript
import { Router } from 'express';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import ExcelJS from 'exceljs';
router.get('/download-csv', (req, res) => {
const csvData = `Name,Email,Phone
John Doe,john@example.com,123-456-7890
Jane Smith,jane@example.com,987-654-3210`;
const buffer = Buffer.from(csvData);
res.setHeader('Content-Type', 'text/csv');
res.setHeader('Content-Disposition', 'attachment; filename="example.csv"');
res.setHeader('Content-Length', buffer.length);
res.end(buffer);
});前端实现
javascript
async download(url: string, method: string, params: any = {}, config: any = {}) {
const reqMethod = method.toLowerCase() as 'get' | 'post';
let response: AxiosResponse;
if (reqMethod === 'get') {
response = await axios.get(url, {
params,
...config,
responseType: 'blob',
});
} else {
response = await axios.post(url, params, {
...config,
responseType: 'blob',
});
}
const blob = response.data;
const link = document.createElement('a');
const contentDisposition = response.headers['content-disposition'];
const fileName = config.filename || 'fileName.xls';
link.download = fileName;
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click(); //点击下载
document.body.removeChild(link); //下载完成移除元素
setTimeout(() => {
URL.revokeObjectURL(link.href); //清除引用
}, 100);
},