SPRINGBOOT实现大文件上传,断点续传,秒传功能
首先要理解,为什么大文件上传跟小文件上传不一样。假设我有个1G的文件或者更大需要上传,如果直接上传的话会有什么弊端?
1.上传过程时间较长
2.中途不能间断,间断之后需要重新上传等
简单来说:大文件上传其实就是前端对文件做一个分片处理,将一个大文件分成很多份小文件上传,后端将小文件进行一个存储合并的过程。
码农最喜欢的搬砖来了,前端基于vue的一个开源插件。大家可以去github上下载。下载地址:https://github.com/pseudo-god/vue-simple-upload
后端代码(仅供参考,实际根据业务进行处理即可,重在理解):
两个处理文件路径和名称的工具类
与数据库对应的持久类
处理前端请求controller类
public class BigFileApi {
@Autowired
private FileSectionService fileSectionService; //操作数据库表的service类
@Value("${custom.upload.dir}")
private String upLoadDir ; //文件的存储路径
@Autowired
private IACLNodeApi aclNodeApi ;
/**
* 大文件上传 超过500M 理论无上限
* @param request
* @param multipartFile 文件块
* @return
* @throws IllegalStateException
* @throws IOException
* */
@ApiOperation(value="大文件上传 超过500M 理论无上限")
@RequestMapping(value = "/fileChunk/uploadChunkFile" , method = RequestMethod.POST)
public APIResult<Map<String,Object>> uploadBigFile(HttpServletRequest request, @RequestParam(value = "file",required = false) MultipartFile multipartFile) {
UserBean user = UserHolder.getUser();
if(user == null ){
return new APIResult<Map<String,Object>>("请先登陆" , SystemConst.SYSTEM_STATUS_FALSE.getState());
}
Map<String,Object> map = Maps.newHashMap();
String bigFileId = request.getParameter("id");
String md5 = request.getParameter("md5"); //分片的md5 和整个文件的md5相同 这里可以忽略
String fileName = request.getParameter("fileName"); //
int index = Integer.parseInt(fileName);
FileSection recordById = fileSectionService.findById(bigFileId);
if (recordById == null){
return new APIResult<Map<String,Object>>("上传失败,参数错误!" , SystemConst.SYSTEM_STATUS_FALSE.getState());
}
if (recordById.getFileStatus() ==1){
return new APIResult<Map<String,Object>>("文件已经存在,请勿重复上传" , SystemConst.SYSTEM_STATUS_FALSE.getState());
}
//文件夹路径
String saveDirectory= FileOperaHelper.CreatePath(upLoadDir,recordById.getFileDate(),recordById.getUuid());
//分片文件
File path = new File(saveDirectory);
if (!path.exists()) {
path.mkdirs();
}
File file = new File(saveDirectory, recordById.getUuid() + "_" + index);
FileSection fileSectionRecordUpload = new FileSection();
//先删除后上传
if (file.exists