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 },