java大文件上传/下载解决方案整理

发布时间 2023-09-18 09:42:41作者: Xproer-松鼠

分片上传、断点续传、秒传
文件上传花样百出,根据不同场景使用不同方案进行实现尤为必要。通常开发过程中,文件较小,直接将文件转化为字节流上传到服务器,但是文件较大时,用普通的方法上传,显然效果不是很好,当文件上传一半中断再次上传时,发现需要重新开始,这种体验不是很爽,下面介绍几种好一点儿的上传方式。

1. 分片上传
1.1 什么是分片上传
分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分
隔成多个数据块(我们称之为Part)来进行分别上传,上传完之后再
由服务端对所有上传的文件进行汇总整合成原始的文件。
1.2 分片上传的场景
大文件上传
网络环境不好或者存在需要重传的风险
2.断点续传
2.1 什么是断点续传
断点续传是在下载/上传时,将下载/上传任务(一个文件或一个压缩
包)人为的划分为几个部分,每一个部分采用一个线程进行上传/下载,
如果碰到网络故障,可以从已经上传/下载的部分开始继续上传/下载
未完成的部分,而没有必要从头开始上传/下载。
2.2 应用场景
断点续传可以看成是分片上传的一个衍生,因此可以使用分片上传的场景,都可以使用断点续传。

2.3 实现断点续传的核心逻辑
在分片上传的过程中,如果因为系统崩溃或者网络中断等异常因素导致上传中断,这时客户端需要记录上传的进度。后续支持再次上传时,可以继续从上次上传中断的地方进行继续上传。
为了避免客户端在上传之后的进度数据被删除而导致重新开始从头上传的问题,服务端也可以提供相应的接口便于客户端对已经上传的分片数据进行查询,从而使客户端知道已经上传的分片数据,从下一个分片数据开始继续上传。

整体的过程如下:

前端将文件按照百分比进行计算,每次上传文件的百分之一(文件分片),给文件分片做上序号
后端将前端每次上传的文件,放入到缓存目录
等待前端将全部的文件内容都上传完毕后,发送一个合并请求
后端使用RandomAccessFile进多线程读取所有的分片文件,一个线程一个分片
后端每个线程按照序号将分片的文件写入到目标文件中
在上传文件的过程中发生断网了或者手动暂停了,下次上传的时候发送续传请求,让后端删除最后一个分片
前端重新发送上次的文件分片
整体实现流程如下:

 


3.秒传
3.1 什么是秒传
通俗的说,你把要上传的东西上传,服务器会先做MD5校验,如果服务
器上有一样的东西,它就直接给你个新地址,其实你下载的都是服务器
上的同一个文件,想要不秒传,其实只要让MD5改变,就是对文件本身
做一下修改(改名字不行),例如一个文本文件,你多加几个字,MD5
就变了,就不会秒传了。
3.2 实现秒传的核心逻辑
使用redis的set方法存放文件上传状态,其中key为文件上传的md5,value为是否上传完成的标志位,当标志位true为上传已经完成,此时如果有相同文件上传,则进入秒传逻辑。
如果标志位为false,则说明还没上传完成,此时需要在调用set的方法,保存块号文件记录的路径,其中key为上传文件md5加一个固定前缀,value为块号文件记录路径。

 

 

 

参考文章:http://blog.ncmem.com/wordpress/2023/09/18/java%e5%a4%a7%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0-%e4%b8%8b%e8%bd%bd%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e6%95%b4%e7%90%86/

欢迎入群一起讨论