首先要理解,为什么大文件上传跟小文件上传不一样。假设我有个1G的文件或者更大需要上传,如果直接上传的话会有什么弊端?

1.上传过程时间较长

2.中途不能间断,间断之后需要重新上传等


简单来说:大文件上传其实就是前端对文件做一个分片处理,将一个大文件分成很多份小文件上传,后端将小文件进行一个存储合并的过程。

码农最喜欢的搬砖来了,前端基于vue的一个开源插件。大家可以去github上下载。下载地址:https://github.com/pseudo-god/vue-simple-upload
后端代码(仅供参考,实际根据业务进行处理即可,重在理解):

两个处理文件路径和名称的工具类

SPRINGBOOT实现大文件上传,断点续传,秒传功能_上传

 


SPRINGBOOT实现大文件上传,断点续传,秒传功能_大文件上传_02

 


与数据库对应的持久类

SPRINGBOOT实现大文件上传,断点续传,秒传功能_大文件上传_03

 


处理前端请求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