SpringBoot实现对文件的断点续传和秒传
本文断点续传文件思路:
- 前端(客户端)需要根据固定大小对文件进行分片,请求后端(服务端)时要带上分片序号和大小;
- 服务端创建conf文件用来记录分块位置,conf文件长度为总分片数,每上传一个分块即向conf文件中写入一个127,那么没上传的位置就是默认的0,已上传的就是Byte.MAX_VALUE 127(这步是实现断点续传和秒传的核心步骤);
- 服务器按照请求数据中给的分片序号和每片分块大小(分片大小是固定且一样的)算出开始位置,与读取到的文件片段数据,写入文件。
分片上传/断点续传测试验证:
1、分片上传
2、断点续传
演示步骤:
a、文件上传一定大小,关闭浏览器,模拟中断,此时上传服务器中会有如下内容:
打开conf文件,会有如下内容:
其中小方形为已经上传的块号
b、浏览器继续上传同一份文件
秒传
1、什么是秒传
通俗的说,你把要上传的东西上传,服务器会先做MD5校验,如果服务器上有一样的东西,它就直接给你个新地址,其实你下载的都是服务器上的同一个文件,想要不秒传,其实只要让MD5改变,就是对文件本身做一下修改(改名字不行),例如一个文本文件,你多加几个字,MD5就变了,就不会秒传了。
2、本文实现的秒传核心逻辑
a、利用redis的set方法存放文件上传状态,其中key为文件上传的md5,value为是否上传完成的标志位;
b、当标志位true为上传已经完成,此时如果有相同文件上传,则进入秒传逻辑。如果标志位为false,则说明还没上传完成,此时需要在调用set的方法,保存块号文件记录的路径,其中key为上传文件md5加一个固定前缀,value为块号文件记录路径。
3、核心代码逻辑
private boolean setUploadProgress2Redis(FileUploadRequestDTO param, String uploadDirPath, String fileName, File confFile, byte isComplete) { RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class); if (isComplete == Byte.MAX_VALUE) { redisUtil.hset(FileConstant.FILE_UPLOAD_STATUS, param.getMd5(), "true"); redisUtil.del(FileConstant.FILE_MD5_KEY + param.getMd5()); confFile.delete(); return true; } else { if (!redisUtil.hHasKey(FileConstant.FILE_UPLOAD_STATUS, param.getMd5())) { redisUtil.hset(FileConstant.FILE_UPLOAD_STATUS, param.getMd5(), "false"); redisUtil.set(FileConstant.FILE_MD5_KEY + param.getMd5(), uploadDirPath + FileConstant.FILE_SEPARATORCHAR + fileName + ".conf"); } return false; } }
参考文章:http://blog.ncmem.com/wordpress/2023/10/25/springboot%e5%ae%9e%e7%8e%b0%e5%af%b9%e6%96%87%e4%bb%b6%e7%9a%84%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0%e5%92%8c%e7%a7%92%e4%bc%a0/
欢迎入群一起讨论