java⼤⽂件(百M以上)的上传下载⽅法
核⼼原理:
* 如何分⽚;
* 如何合成⼀个⽂件;
* 中断了从哪个分⽚开始。
如何分,利⽤强⼤的js库,来减轻我们的⼯作,市场上已经能有关于⼤⽂件分块的轮⼦,虽然程序员的天性曾迫使我重新造轮⼦。但是因为时间的关系还有⼯作的关系,我只能罢休了。最后我选择了百度的WebUploader来实现前端所需。
如何合,在合之前,我们还得先解决⼀个问题,我们如何区分分块所属那个⽂件的。刚开始的时候,我是采⽤了前端⽣成了唯⼀uuid来做⽂件的标志,在每个分⽚请求上带上。不过后来在做秒传的时候我放弃了,采⽤了Md5来维护分块和⽂件关系。
在服务端合并⽂件,和记录分块的问题,在这⽅⾯其实⾏业已经给了很好的解决⽅案了。参考迅雷,你会发现,每次下载中的时候,都会有两个⽂件,⼀个⽂件主体,另外⼀个就是⽂件临时⽂件,临时⽂件存储着每个分块对应字节位的状态。
这些都是需要前后端密切联系才能做好,前端需要根据固定⼤⼩对⽂件进⾏分⽚,并且请求中要带上分⽚序号和⼤⼩。前端发送请求顺利到达后台后,服务器只需要按照请求数据中给的分⽚序号和每⽚分块⼤⼩(分⽚⼤⼩是固定且⼀样的)算出开始位置,与读取到的⽂件⽚段数据,写⼊⽂件即可。
为了便于开发,我 将服务端的业务逻辑进⾏了如下划分,分成初始化,块处理,⽂件上传完毕等。
服务端的业务逻辑模块如下
功能分析:大文件发送
⽂件夹⽣成模块
⽂件夹上传完毕后由服务端进⾏扫描代码如下
分块上传,分块处理逻辑应该是最简单的逻辑了,up6已经将⽂件进⾏了分块,并且对每个分块数据进⾏了标识,这些标识包括⽂件块的索引,⼤⼩,偏移,⽂件MD5,⽂件块MD5(需要开启)等信息,服务端在接收这些信息后便可以⾮常⽅便的进⾏处理了。⽐如将块数据保存到分布式存储系统中
分块上传可以说是我们整个项⽬的基础,像断点续传、暂停这些都是需要⽤到分块。
分块这块相对来说⽐较简单。前端是采⽤了webuploader,分块等基础功能已经封装起来,使⽤⽅便。借助webUpload提供给我们的⽂件API,前端就显得异常简单。
前台HTML模板
分则必合。把⼤⽂件分⽚了,但是分⽚了就没有原本⽂件功能,所以我们要把分⽚合成为原本的⽂件。我们只需要把分⽚按原本位置写⼊到⽂件中去。因为前⾯原理那⼀部我们已经讲到了,我们知道分块⼤⼩和分块序号,我就可以知道该分块在⽂件中的起始位置。所以这⾥使⽤RandomAccessFile是明智的,RandomAccessFile能在⽂件⾥⾯前后移动。但是在andomAccessFile的绝⼤多数功能,已经被JDK1.4的NIO的“内存映射⽂件(memory-mapped files)”取代了。我在该项⽬中分别写了使⽤RandomAccessFile与MappedByteBuffer来合成⽂件。分别对应的⽅法是uploadFileRandomAccessFile和uploadFileByMappedByteBuffer。两个⽅法代码如下。
秒传功能
服务端逻辑
秒传功能,相信⼤家都体现过了,⽹盘上传的时候,发现上传的⽂件秒传了。其实原理稍微有研究过的同学应该知道,其实就是检验⽂件MD5,记录下上传到系统的⽂件的MD5,在⼀个⽂件上传前先获取⽂件内容MD5值或者部分取值MD5,然后在匹配系统上的数据。
Breakpoint-http实现秒传原理,客户端选择⽂件之后,点击上传的时候触发获取⽂件MD5值,获取MD5后调⽤系统⼀个接⼝
(/index/checkFileMd5),查询该MD5是否已经存在(我在该项⽬中⽤redis来存储数据,⽤⽂件MD5值来作key,value是⽂件存储的地址。)接⼝返回检查状态,然后再进⾏下⼀步的操作。相信⼤家看代码就能明⽩了。
嗯,前端的MD5取值也是⽤了webuploader⾃带的功能,这还是个不错的⼯具。
发布评论