前端文件下载实战:从原理到最佳实践
引言
在现代 Web 应用开发中,文件下载是一个常见但容易出错的场景。本文将通过一个真实的订单导出功能案例,详细介绍前后端协作实现文件下载的完整方案,分析常见问题及解决方案,并提供经过生产验证的最佳实践。
一、需求背景与初始实现
1.1 业务需求
我们需要实现一个订单数据导出功能,允许用户将查询结果下载为 Excel 文件。具体要求包括:
- 支持按任务 ID 筛选订单
- 生成规范的 XLSX 格式文件
- 显示友好的下载状态
- 记录操作日志
1.2 初始后端实现
@ApiOperation(value ="下载订单列表", notes ="根据条件导出订单数据为 Excel 文件")
@PostMapping("/order-list/download")
public Result<?> downloadTaskOrderExcel(@RequestBody TaskDownLoadRequest taskDownLoadRequest, HttpServletRequest httpRequest){
try{
// 获取用户 ID 并记录日志
Integer userId = getUserId(taskDownLoadRequest.getTaskId());
logDownloadStart(userId, taskDownLoadRequest.getTaskId());
// 查询订单数据
List<CustomerOrder> orders = queryOrders(taskDownLoadRequest.getTaskId());
if(orders.isEmpty()){
return Result.error("没有找到符合条件的订单数据");
}
// 生成 Excel 文件
ByteArrayResource resource = generateExcel(orders);
// 构建响应数据
Map<String,Object> data = buildResponseData(resource);
return Result.ok(data);
}catch(Exception e){
log.error("下载订单列表失败", e);
return Result.error(500,"下载订单数据失败");
}
}
1.3 初始前端实现
const download=async(row)=>{
loading = .({ :})
{
response = commonApi.({ : row. },{ :})
filename =;
disposition = response.[];
(disposition){
match = disposition.();
(match) filename =(match[]);
}
blob = ([response.],{ :});
link = .();
link. = ..(blob);
link. = filename;
..(link);
link.();
..(link);
.();
}(e){
.();
}{
loading.();
}
}


