【Easylive】分片上传视频文件 uploadVideo方法
【Easylive】项目常见问题解答(自用&持续更新中…) 汇总版
这段代码实现了一个 分片上传视频文件 的功能,主要用于处理大文件的上传(如视频)。以下是逐行解析:
1. 方法签名
@RequestMapping("/uploadVideo")
@GlobalInterceptor(checkLogin = true) // 需要登录验证
public ResponseVO uploadVideo(
@NotNull MultipartFile chunkFile, // 当前上传的文件分片
@NotNull Integer chunkIndex, // 当前分片的索引(从0或1开始)
@NotEmpty String uploadId // 本次上传的唯一标识
) throws IOException {
• 作用:接收客户端上传的视频文件分片,并保存到服务器临时目录。
• 参数说明:
• chunkFile
:当前上传的文件分片(MultipartFile
类型)。
• chunkIndex
:当前分片的序号(如第1片、第2片)。
• uploadId
:唯一标识本次上传任务(用于关联所有分片)。
2. 用户身份验证
TokenUserInfoDto tokenUserInfoDto = getTokenUserInfoDto();
• getTokenUserInfoDto()
:
从请求头或 Cookie 获取当前登录用户的信息(如 userId
)。
3. 检查上传任务是否存在
UploadingFileDto fileDto = redisComponent.getUploadVideoFile(tokenUserInfoDto.getUserId(), uploadId);
if (fileDto == null) {
throw new BusinessException("文件不存在请重新上传");
}
• UploadingFileDto
:
存储在 Redis 中的上传任务信息,包含:
• filePath
:文件存储路径。
• chunks
:总分片数。
• chunkIndex
:已上传的最大分片索引。
• fileSize
:已上传的文件总大小。
• 逻辑:如果 Redis 中没有找到对应的上传任务,说明任务已过期或无效,需重新上传。
4. 检查文件大小限制
SysSettingDto sysSettingDto = redisComponent.getSysSettingDto();
if (fileDto.getFileSize() > sysSettingDto.getVideoSize() * Constants.MB_SIZE) {
throw new BusinessException("文件超过最大文件限制");
}
• sysSettingDto.getVideoSize()
:
从系统配置中获取允许的最大视频文件大小(单位:MB)。
• 逻辑:如果已上传的文件总大小超过限制,直接拒绝。
5. 检查分片序号合法性
if ((chunkIndex - 1) > fileDto.getChunkIndex() || chunkIndex > fileDto.getChunks() - 1) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
• 分片顺序校验:
• chunkIndex - 1 > fileDto.getChunkIndex()
:当前分片比预期分片大(如预期传第3片,但传了第5片)。
• chunkIndex > fileDto.getChunks() - 1
:当前分片超过总分片数。
• 目的:防止乱序上传或恶意传超出范围的分片。
6. 保存分片文件
String folder = appConfig.getProjectFolder() + Constants.FILE_FOLDER + Constants.FILE_FOLDER_TEMP + fileDto.getFilePath();
File targetFile = new File(folder + "/" + chunkIndex);
chunkFile.transferTo(targetFile);
• 临时目录结构:
项目根目录/upload/temp/{uploadId}/0,1,2,...
(每个分片以索引命名)。
• transferTo()
:
将分片文件保存到目标路径(如 /data/project/upload/temp/abc123/1
)。
7. 更新上传进度
fileDto.setChunkIndex(chunkIndex); // 更新已上传的最大分片索引
fileDto.setFileSize(fileDto.getFileSize() + chunkFile.getSize()); // 累加文件大小
redisComponent.updateVideoFileInfo(tokenUserInfoDto.getUserId(), fileDto); // 更新Redis
• 作用:记录当前上传进度,确保断点续传时能正确恢复。
8. 返回成功响应
return getSuccessResponseVO(null);
• 返回空响应(HTTP 200),表示当前分片上传成功。
完整流程总结
- 客户端:
• 将大文件切分为多个分片(如每片5MB)。
• 依次调用/uploadVideo
上传每个分片,携带uploadId
和chunkIndex
。 - 服务端:
• 检查分片顺序、大小限制。
• 保存分片到临时目录。
• 更新 Redis 中的上传进度。 - 最终合并(需另接接口):
所有分片上传完成后,调用合并接口将临时文件拼接为完整视频。
优化建议
- 断点续传:
• 客户端记录已上传的分片,服务端返回缺失的分片索引。 - 分片校验:
• 对每个分片计算 MD5,确保传输完整性。 - 清理临时文件:
• 上传完成后删除临时分片,或设置过期时间自动清理。 - 并发控制:
• 限制同一uploadId
的并发上传请求,避免分片错乱。
适用场景
• 视频网站(如用户上传高清视频)。
• 云存储服务(如网盘的大文件上传)。
• 企业内部分享大文件。