1、背景:
系统中有个文件下载的功能,下载的文件从1k-几十G不等,小文件下载没有问题,只要上G了,下载大概率失败。基于以上现状,对技术方案记性优化。
2、历史方案:
2.1 服务器读取文件流传输+前端blob接收
描述:
- 后端接口通过response的IO通道,读写文件流传输
- 前端接收Blob数据,等所有接收完成,再保存成文件
优点:传统方案,方案固定好写
缺点:文件先读到内存再输出,存在服务器压力;大文件传输过程中客户端和服务器的连接管道容易断开:broken pieped;前端接收内存压力;进度需要自己记录和计算;
2.2 使用NIO读取写入(同上)
描述:传输速度比BIO能快10倍以内
优缺点同上;
2.3 分片下载
描述:前端和后端都使用分片下载,等前端把所有的分片下载完成再合并成一个文件;
优缺点同上;能减少连接断开的概率;
3、完美方案:
目标:有进度显示;能正常下载完成;多人下载无压力;
描述:
- 进度显示:前端使用window.location.href=下载文件连接 的形式;
- 后端接口改成GET接口,参数拼接在url后面,包括token:因为href是新启动一个请求,并且header不能自定义,所以接口的鉴权只能放在url后面;
- 后端接口对url参数和token进行验证;
- 开始后端接口逻辑:
- 获取文件路径,设置response的header属性,重定向到Nginx配置的内部文件路由
- nginx返回文件信息
- 浏览器接收并在下方显示下载进度
Nginx.conf配置文章来源:https://www.toymoban.com/news/detail-579135.html
location /ngdownload {
alias /opt/data;#文件目录的前缀
internal;#标识内部接口
}
Java代码:文章来源地址https://www.toymoban.com/news/detail-579135.html
public void downloadByLink(HttpServletResponse response, String fileId) {
//查询附件信息
File file = getFile();//自己实现
//鉴权实际已经通过gateway完成
try {
String fileName = URLEncoder.encode(file.getName(), "UTF-8");
//Content-Disposition 表示文件的下载方式,attachment 表示文件需要下载,而不是在浏览器中打开
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
//设置URI给nginx进行内部的跳转/ngndownload
response.setHeader("X-Accel-Redirect", "/ngndownload" + fileName );
//限速 尽量不设置
response.setHeader("X-Accel-Limit-Rate", "202400");
} catch (UnsupportedEncodingException e) {
log.error("文件下载失败 ", e);
throw new BusinessException("文件下载失败");
}
}
到了这里,关于大文件下载优化方案(nginx+Springboot+vue)---非常完美的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!