问题
上传业务,有的文件比较大,比如视频文件,小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:
1、文件过大,超出服务端的请求大小限制; 2、请求时间过长,请求超时; 3、传输中断,必须重新上传导致前功尽弃;
解决方案
分片上传的整个流程大致如下:
将需要上传的文件按照一定的分割规则,分割成相同大小的数据块;
初始化一个分片上传任务,返回本次分片上传唯一标识;
按照一定的策略(串行或并行)发送各个分片数据块;
发送完成后,服务端根据判断数据上传是否完整,如果完整,则进行数据块合成得到原始文件
分片上传断点续传
上传的前端代码在 upload.html
内
后端代码在 com.example.demo.controller.Uploader
内
前端
本次上传使用的前端插件为 WebUploader
, 想要支持分片,需要配置开启分片
分片设置 |
---|
// 这里只显示文档需要的,其他的属性请自行配置 var uploader = WebUploader.create({ // 开启分片上传 chunked: true, // 每个分片的大小,5M chunkSize: 5 * 1024 * 1024, // 上传线程 threads: 3 }); |
其中 WebUploader
如下的几个方法需要进行配置,这些方法及涵义如下:
- beforeSendFile 在所有分块上传前触发,校验文件是否存在,如果存在则不上传
- beforeSend 在每个分片上传前触发,校验当前文件是否存在,如果存在则跳过
- uploadBeforeSend 文件上传,如果需要分片则需要在 data 内添加 md5 唯一值
- afterSendFile 在所有分片上传完成之后触发,用于合成分片
上传的前端代码可以在 upload.html
内找到,具体实现可以参考代码。
由于需要进行 md5 做hash判断文件是否存在,因此存在一个 md5js.js
文件,需要引入在实际代码内。
后端
后端代码在 com.example.demo.controller.Uploader
内,与前端触发事件的方法相对应,如下所示
- checkFile 用于检测文件是否存在实现MD5秒传,具体校验逻辑应该由业务决定,这个需要自行添加校验代码
当文件体积大、量比较多时,支持上传前做文件md5值验证,一致则可直接跳过。
如果服务端与前端统一修改算法,取段md5,可大大提升验证性能,耗时在20ms左右。
- checkChunk 用于校验分片是否存在。需要修改 分片存放目录,实现断点续传。
- upload 用于实现实际的文件上传逻辑。需要修改 分片存放目录
- merge 用于合并所有分片,此处需要修改 分片存放目录、文件存放目录。并在合并完文件之后,将 md5 保存在数据库或者缓存中,此处由具体业务逻辑实现。
代码
使用idea打开项目,启动后通过http://localhost:8080/ 访问。资源下载链接。