(含完整项目)springboot+webuploader+mysql实现大文件分片、可以关掉浏览器的断点上传、秒传

完整项目在此:https://github.com/NoonLoveSnow/bigfileupload.git

先说下为什么用数据库记录文件分片,因为文件分片可能不会存储在本机上,用数据库可以记录分片存储位置,方便获取。。合并后的文件也可以记录其md5值,作为真实文件,用户文件可以只需要新建表引用它就行了。

大文件传输主要注意的有以下几点:

大文件传输要求

大文件传输往往是比较耗时的,所以要求传输操作可继续的即断点续传,不能因为一些故障导致重新上传整个文件。

断点续传思路:

在浏览器传输时需要将文件分片上传,当遇到意外情况继续上传时,则之前传输完成的分片就不用传输了而传输未上传成功的分片。

如何记录上传成功的分片:

文件MD5与分片编号作为联合主键记录在数据库中。

分片上传前如何判断分片已经传输完成:

数据库中有记录,且文件长度与分片大小(chunkSize)相等

合并后文件校验:

文件大小是否不一致,每个分片应有的大小加起来与合并后的文件相比较

关于WebUploader:

网上有很多教程和例子。。

主要代码

后端:

package com.noonsnow.bigfileupload.controller;

import com.alibaba.fastjson.JSONObject;

import com.noonsnow.bigfileupload.mapper.FileBlockMapper;
import com.noonsnow.bigfileupload.mapper.UploadFileMapper;
import com.noonsnow.bigfileupload.pojo.FileBlock;
import com.noonsnow.bigfileupload.pojo.UploadFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Date;
import java.util.List;

//http://localhost:8081/uploadPage
@Controller
public class FileUploadController {
    @Autowired
    FileBlockMapper blockMapper;
    @Autowired
    UploadFileMapper fileMapper;

    final static String filesDir = "C:/files";
    final static String blocksDir = "C:/bolcks";

    @RequestMapping("uploadPage")
    public String page() {
        return "bigFileUpload";
    }


    @PostMapping("checkFileIsExist")//检查文件是否存在
    @ResponseBody
    public Object checkFileExist(String md5value) {
        JSONObject resp = new JSONObject();
        List<UploadFile> uploadFiles = fileMapper.getByMd5(md5value);//逻辑上只有一个文件,由于不是按主键查找返回的是一个List
        if (uploadFiles.size() == 0)
            resp.put("exist", "0");
        else
            resp.put("exist", 1);
        return resp.toString();
    }


    @PostMapping("checkChunkIsExist")//检查分片是否存在且完整
    @ResponseBody
    public Object checkChunkExist(String md5value, int chunk, int chunkSize) {

        JSONObject resp = new JSONObject();

        //查数据库,分片是否存在
        FileBlock fileBlock = blockMapper.getByMd5AndChunk(md5value, chunk);

        if (fileBlock == null) {//数据库不存在分片记录或者分片不完整,则重传
            resp.put("exist", "0");
            return resp.toString();
        }

        File block = new File(blocksDir + "/" + md5value + "/" + chunk); //前面没通过就不用执行后面的了,性能会好点吧。。
        // System.out.println("blocklen:"+block.length()+"  "+"chunkSize:"+chunkSize);
        if (block.length() != chunkSize) {//分片是否完整
            resp.put("exist", "0");
            return resp.toString();
        }

        resp.put("exist", "1");
        return resp.toString();

    }


    @PostMapping("upload")//接收上传的分片
    @ResponseBody
    public String fileUpload(String md5value, String chunks, int chunk, String id, String name,
                             String type, String lastModifiedDate, int chunkSize, MultipartFile file) {

        //-----------------------保存分片--------------------
        File blockDir = new File(blocksDir + "/" + md5value);
        blockDir.mkdirs();
        File block = new File(blockDir, String.valueOf(chunk));
        try {
            //搞了N多天,WebUploader tmd要重复发送验证通过的分片,导致多插入数据,导致合并文件变大,坑 (其实还是之前我没把MD5和chunk弄成联合主键,不然它重复插入不了的,自作孽啊)
            boolean exist = blockMapper.getByMd5AndChunk(md5value, chunk) == null ? false : true;
            if (!exist) {
                FileBlock fileBlock = new FileBlock(md5value, new Date(), block.getPath(), chunk, name, chunkSize);
                blockMapper.addFileBlock(fileBlock);//增加分片记录
            }
            file.transferTo(block);

        } ca
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值