1、简述
在开发过程中,不可避免会遇到前端查询或者直接导出大文件,这个时候对于客户而已如何简洁明了的体验尤为重要。所以既需要优化前端操作的用户体验,也需要优化后端的数据处理和传输效率。以下是前端和后端的优化方案:
2、前端
2.1 异步处理和进度反馈
- 异步请求:使用异步请求(AJAX 或 Fetch API)启动导出操作,避免阻塞用户界面。
- 进度反馈:提供导出进度的反馈,例如显示加载动画或进度条,让用户了解导出进度。
// 发起异步请求
async function exportFile() {
try {
let response = await fetch('/api/export', { method: 'POST' });
if (!response.ok) throw new Error('Network response was not ok');
let result = await response.json();
// 显示下载链接
showDownloadLink(result.downloadUrl);
} catch (error) {
console.error('Error during file export:', error);
}
}
2.2 文件分块下载
如果文件非常大,可以考虑分块下载,前端合并。这可以通过分块请求后端来实现,逐步下载文件块并合并:
async function downloadFileInChunks(url, chunkSize = 1024 * 1024) {
let response = await fetch(url, { method: 'HEAD' });
let fileSize = parseInt(response.headers.get('Content-Length'));
let start = 0;
let chunks = [];
while (start < fileSize) {
let end = Math.min(start + chunkSize, fileSize);
let chunk = await fetch(`${url}?range=${start}-${end}`);
chunks.push(await chunk.blob());
start = end;
}
let fileBlob = new Blob(chunks);
let downloadUrl = URL.createObjectURL(fileBlob);
download(downloadUrl);
}
function download(url) {
let a = document.createElement('a');
a.href = url;
a.download = 'exported_file';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
2.3 流式下载
利用浏览器的流式下载功能,边下载边保存,减少内存占用。
async function streamDownload(url) {
const response = await fetch(url);
const reader = response.body.getReader();
const stream = new ReadableStream({
start(controller) {
function push() {
reader.read().then(({ done, value }) => {
if (done) {
controller.close();
return;
}
controller.enqueue(value);
push();
});
}
push();
}
});
const blob = await new Response(stream).blob();
const downloadUrl = URL.createObjectURL(blob);
download(downloadUrl);
}
3、后端
3.1 分批处理
对于非常大的数据集,避免一次性加载全部数据到内存,可以采用分批处理方式,逐步读取和处理数据。
public class DataService {
public List<Data> getDataBatch(int offset, int batchSize) {
// 从数据库或其他数据源获取一批数据
// 假设这里返回一个包含批量数据的列表
return dataRepository.findDataBatch(offset, batchSize);
}
}
3.2 使用 SXSSFWorkbook
Apache POI 提供了 SXSSFWorkbook 用于处理大文件,它基于流式 API,在内存中只保留有限数量的行。
try (SXSSFWorkbook workbook = new SXSSFWorkbook()) {
Sheet sheet = workbook.createSheet("Data");
// 逐行写入数据,SXSSFWorkbook自动处理内存中的行数
for (int i = 0; i < totalRows; i++) {
Row row = sheet.createRow(i);
// 创建单元格并填充数据
}
workbook.write(outputStream);
}
3.3 流式传输
使用 HTTP 的流式传输,将数据逐行写入响应,避免后端内存占用过高。
@PostMapping("/stream-export-excel")
public void streamExportExcel(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=largefile.xlsx");
try (ServletOutputStream outputStream = response.getOutputStream();
SXSSFWorkbook workbook = new SXSSFWorkbook()) {
Sheet sheet = workbook.createSheet("Data");
int batchSize = 1000;
int rowCount = 0;
List<Data> dataBatch;
do {
dataBatch = dataService.getDataBatch(rowCount, batchSize);
for (Data data : dataBatch) {
Row row = sheet.createRow(rowCount++);
createCells(row, data);
}
} while (dataBatch.size() == batchSize);
workbook.write(outputStream);
}
}
private void createCells(Row row, Data data) {
Cell cell0 = row.createCell(0);
cell0.setCellValue(data.getField0());
// ... 创建其他单元格
}
3.4 文件缓存
对于需要重复下载的大文件,可以预先生成文件并缓存到磁盘或云存储,每次导出时直接返回文件链接。
@PostMapping("/export")
public ResponseEntity<String> exportFile() {
String filePath = fileService.generateAndCacheFile();
String fileUrl = fileService.getDownloadUrl(filePath);
return ResponseEntity.ok(fileUrl);
}
// FileService.java
public String generateAndCacheFile() {
String filePath = "/path/to/cache/largefile.xlsx";
try (SXSSFWorkbook workbook = new SXSSFWorkbook()) {
Sheet sheet = workbook.createSheet("Data");
// 填充数据
try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
workbook.write(fileOut);
}
} catch (IOException e) {
e.printStackTrace();
}
return filePath;
}
public String getDownloadUrl(String filePath) {
return "https://your-domain.com/download?file=" + filePath;
}
4、总结
通过前端的异步处理、进度反馈、分块下载和流式下载,可以提升用户体验和下载效率。后端则通过分批处理、流式传输、SXSSFWorkbook、EasyExcel和文件缓存,减少内存压力,提高导出性能。通过这两方面的优化,可以有效提升导出大文件的整体性能和用户体验。
评论区