一、课程介绍
【课程名称】SpringBoot 2.x 实战仿B站高性能后端项目。
【章节】第四章 4.7 断点续传(下)
【讲师】HELLOSTAR
二、课程内容
分片上传文件
1.分片上传文件实现逻辑
将上传的整个文件预先分片,得到分片的总数量和一些小片的文件。按照分片编号顺序进行上传。
为每个文件生成唯一的MD5加密码,作为Redis中存储的唯一key值。使用Redis缓存数据库来记录当前上传文件保存路径,当前上传的文件分片编号和已上传文件的大小。
逐片上传实际使用的是FastDFS中的修改续传文件的内容方法(modifyFile)每一片文件都执行一次。当文件上传完成,即当前文件分片编号等于分片总编号。则清空Redis中存储的数据。
2. 实现代码
/**
* 分片上传文件功能
* 配合Redis使用
* @param file 上传的文件
* @param fileMd5 文件加密唯一编号
* @param sliceNo 分片编号
* @param totalSliceNo 分片总数量
* @return
* @throws Exception
*/
public String uploadFileBySlices(MultipartFile file, String fileMd5, Integer sliceNo, Integer totalSliceNo) throws Exception {
if(file == null || sliceNo == null || totalSliceNo == null){
throw new ConditionException("参数异常!");
}
String pathKey = PATH_KEY + fileMd5;
String uploadedSizeKey = UPLOADED_SIZE_KEY + fileMd5;
String uploadedNoKey = UPLOADED_NO_KEY + fileMd5;
String uploadedSizeStr = redisTemplate.opsForValue().get(uploadedSizeKey);
Long uploadedSize = 0L;
if(!StringUtil.isNullOrEmpty(uploadedSizeStr)){
uploadedSize = Long.valueOf(uploadedSizeStr);
}
if(sliceNo == 1){ //上传的是第一个分片
String path = this.uploadAppenderFile(file);
if(StringUtil.isNullOrEmpty(path)){
throw new ConditionException("上传失败!");
}
redisTemplate.opsForValue().set(pathKey, path);
redisTemplate.opsForValue().set(uploadedNoKey, "1");
}else{
String filePath = redisTemplate.opsForValue().get(pathKey);
if(StringUtil.isNullOrEmpty(filePath)){
throw new ConditionException("上传失败!");
}
this.modifyAppenderFile(file, filePath, uploadedSize);
redisTemplate.opsForValue().increment(uploadedNoKey);
}
// 修改历史上传分片文件大小
uploadedSize += file.getSize();
redisTemplate.opsForValue().set(uploadedSizeKey, String.valueOf(uploadedSize));
//如果所有分片全部上传完毕,则清空redis里面相关的key和value
String uploadedNoStr = redisTemplate.opsForValue().get(uploadedNoKey);
Integer uploadedNo = Integer.valueOf(uploadedNoStr);
String resultPath = "";
if(uploadedNo.equals(totalSliceNo)){
resultPath = redisTemplate.opsForValue().get(pathKey);
List<String> keyList = Arrays.asList(uploadedNoKey, pathKey, uploadedSizeKey);
redisTemplate.delete(keyList);
}
return resultPath;
}
三、课程收获
文件分片上传的实际功能代码。结合Redis使用实现快速的文件分片上传功能。通用性的功能代码,编写起来十分快速和清晰。