springboot 大文件分片上传
- constant
- entity
- vo
- controller
- utils

大文件分片上传是一种将大文件分割成多个小文件片段,然后分别上传这些小文件片段的方法。这种方法的好处包括:
-  减少重新上传开销:如果网络传输中断,只需重传未上传的部分,而不是整个文件。 
-  提高灵活性:分片大小可以根据实际情况调整,以平衡上传速度和请求次数。 
-  支持断点续传:服务器可以记录已经上传的文件块,以便在中断后继续上传。 
分片上传的流程大致如下:
-  文件分片:首先,对文件进行分片,每个分片的大小可以根据实际情况设定,例如,一个100MB的文件可以分成每个5MB的分片,共20个分片。 
-  计算MD5值:对每个分片计算MD5值,这有助于文件的完整性校验和唯一标识。(这里使用【文件名+文件后缀+文件大小+时间戳】的方式,对当前文件生成了MD5,用来区分不同的文件,保证文件的唯一性。) 
-  上传分片:将每个分片和它的MD5值一起上传到服务器。 
-  服务器校验:服务器接收每个分片并进行校验,确保分片的完整性和正确性。(这里只在文件合并的时候,对文件片数的完整性进行校验。) 
-  文件合并:当所有分片都成功上传后,服务器将它们合并成完整的文件。 
在选择分片大小时,需要权衡请求次数和灵活性。分片太小会增加请求次数和开销,而分片太大则可能减少灵活性。通常,服务器端会有一个固定大小的接收Buffer,分片的大小最好是这个值的整数倍。
此外,前端在开始上传前需要对文件名进行校验,确保文件名不超过最大长度,否则禁止发送请求。
constant
/**
 * 文件上传类型常量类
 **/
public interface FileUploadTypeConstant
{
   
    /**
     * 单文件上传
     */
    String SINGLE = "single";
    /**
     * 分片上传
     */
    String CHUNKS = "chunks";
    /**
     * 文件合并
     */
    String MERGE = "merge";
}
entity
/**
 * @Description 前端统一返回类
 **/
public class ResResult<D>
{
   
    /**
     * 0 为成功,1为失败
     */
    public static final String SUCCESS = "0";
    public static final String FAIL = "1";
    private String code;
    private D data;
    private String msg;
    private ResResult(String code)
    {
   
        this.code = code;
    }
    public static <T> ResResult<T> get(String code)
    {
   
        return new ResResult<>(code);
    }
    public static <T> ResResult<T> success()
    {
   
        return new ResResult<T>(SUCCESS).setMsg("操作成功");
    }
    public static <T> ResResult<T> success(T data)
    {
   
        return new ResResult<T>(SUCCESS).setMsg("操作成功").setData(data);
    }
    public static <T> ResResult<T> success(String msg)
    {
   
        return new ResResult<T>(SUCCESS).setMsg(msg);
    }
    public static <T> ResResult<T> success(String msg, T data)
    {
   
        return new ResResult<T>(SUCCESS).setMsg(msg).setData(data);
    }
    public static <T> ResResult<T> fail()
    {
   
        return new ResResult<T>(FAIL).setMsg("操作失败");
    }
    public static <T> ResResult<T> fail(String msg)
    {
   
        return new ResResult<T>(FAIL).setMsg(msg);
    }
    public static <T> ResResult<T> fail(String msg, T data)
    {
   
        return new ResResult<T>(FAIL).setMsg(msg).setData(data);
    }
    public static <T> ResResult<T> fail(T data)
    {
   
        return new ResResult<T>(FAIL).setMsg("操作失败").setData(data);
    }
    public D getData()
    {
   
        return this.data;
    }
    public ResResult<D> setData(D data)
    {
   
        this.data = data;
        return this;
    }
    public String getCode()
    {
   
        return code;
    }
    public ResResult<D> setCode(String code)
    {
   
        this.code = code;
        return this;
    }
    public String getMsg()
    {
   
        return msg;
    }
    public ResResult<D> setMsg(String msg)
    {
   
        this.msg = msg;
        return this;
    }
    /**
     * 重载空参for 跨服务调用实例化该类用的构造函数
     */
    private ResResult()
    {
   
    }
}
vo
/**
 * 分片文件对象
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FileChunkVO
{
   
    /**
     * 文件MD5校验值
     */
    String md5Check;
    /**
     * 当前分片编号
     */
    int chunkNumber;
    /**
     * 总分片数
     */
    int totalChunks;
    /**
     * 文件名称
     */
    String fileName;
    /**
     * single:单文件;
     * chunks:分片;
     * marge:合并
     */
    String type;
}
controller
包括三个方法,分别是:单文件上传,文件分片上传,文件合并。
    /**
     * 文件上传
     *
     * @param fileChunkVO   分片文件对象
     * @return ResResult对象,表示上传结果
     */
    @ApiOperation(value = "文件上传")
    @PostMapping("/upload")
    public ResResult<?> upload(MultipartFile file, FileChunkVO fileChunkVO)
    {
   
        try
        {
   
            switch (fileChunkVO.getType())
            {
   
            case FileUploadTypeConstant.SINGLE:
                List<Map<String, Object>> list = FileUtils.uploadFiles(new MultipartFile[]
                {
    file },


















