feat(thumbnail-generator): The first visit to the thumbnail is to generate a thumbnail image

This commit is contained in:
BaldHead 2024-06-14 15:51:06 +08:00
parent f743c1f240
commit 83b528a0c2
2 changed files with 118 additions and 99 deletions

View File

@ -8,6 +8,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
* MinioPlus配置类 * MinioPlus配置类
*
* @author contact@liuxp.me * @author contact@liuxp.me
* @since 2024/05/22 * @since 2024/05/22
*/ */
@ -89,7 +90,11 @@ public class MinioPlusProperties {
/** /**
* 是否开启缩略图默认为true * 是否开启缩略图默认为true
*
* @since 2024-06-14 15:47:46
* feature 缩略图懒生成
*/ */
@Deprecated
private boolean enable = true; private boolean enable = true;
/** /**

View File

@ -54,7 +54,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
/** /**
* 上传任务初始化 * 上传任务初始化
* * <p>
* 1.当前用户或其他用户上传过且已完成秒传新增文件元数据 * 1.当前用户或其他用户上传过且已完成秒传新增文件元数据
* 2.当前用户上传过未完成断点续传 * 2.当前用户上传过未完成断点续传
* 3.其他用户上传过未完成断点续传新增文件元数据 * 3.其他用户上传过未完成断点续传新增文件元数据
@ -64,11 +64,10 @@ public class StorageEngineServiceImpl implements StorageEngineService {
* @param fullFileName 文件名含扩展名 * @param fullFileName 文件名含扩展名
* @param fileSize 文件长度 * @param fileSize 文件长度
* @param isPrivate 是否私有 false: true: * @param isPrivate 是否私有 false: true:
*
* @return {@link FileCheckResultVo} * @return {@link FileCheckResultVo}
*/ */
@Override @Override
public FileCheckResultVo init(String fileMd5, String fullFileName, long fileSize, Boolean isPrivate,String userId) { public FileCheckResultVo init(String fileMd5, String fullFileName, long fileSize, Boolean isPrivate, String userId) {
// 根据MD5查询文件是否已上传过 // 根据MD5查询文件是否已上传过
FileMetadataInfoDTO searchDTO = new FileMetadataInfoDTO(); FileMetadataInfoDTO searchDTO = new FileMetadataInfoDTO();
@ -78,10 +77,10 @@ public class StorageEngineServiceImpl implements StorageEngineService {
FileMetadataInfoSaveDTO saveDTO = new FileMetadataInfoSaveDTO(); FileMetadataInfoSaveDTO saveDTO = new FileMetadataInfoSaveDTO();
CreateUploadUrlReqBO bo = new CreateUploadUrlReqBO(); CreateUploadUrlReqBO bo = new CreateUploadUrlReqBO();
if(CollUtil.isNotEmpty(list)){ if (CollUtil.isNotEmpty(list)) {
// 1.当前用户或其他用户上传过且已完成秒传新增文件元数据 // 1.当前用户或其他用户上传过且已完成秒传新增文件元数据
for (FileMetadataInfoVo fileMetadataInfoVo : list) { for (FileMetadataInfoVo fileMetadataInfoVo : list) {
if(fileMetadataInfoVo.getIsFinished()){ if (fileMetadataInfoVo.getIsFinished()) {
// 秒传 // 秒传
saveDTO.setFileKey(IdUtil.fastSimpleUUID()); // 文件KEY saveDTO.setFileKey(IdUtil.fastSimpleUUID()); // 文件KEY
saveDTO.setFileMd5(fileMd5); // 文件md5 saveDTO.setFileMd5(fileMd5); // 文件md5
@ -109,13 +108,13 @@ public class StorageEngineServiceImpl implements StorageEngineService {
boolean isSelf = userUploaded.isPresent(); boolean isSelf = userUploaded.isPresent();
if(!isSelf){ if (!isSelf) {
uploadingMetadata = list.stream() uploadingMetadata = list.stream()
.filter(FileMetadataInfoVo::getIsFinished) .filter(FileMetadataInfoVo::getIsFinished)
.findAny() .findAny()
.orElseGet(() -> list.stream() .orElseGet(() -> list.stream()
.filter(item -> !item.getIsFinished()).findFirst().get()); .filter(item -> !item.getIsFinished()).findFirst().get());
}else{ } else {
uploadingMetadata = userUploaded.get(); uploadingMetadata = userUploaded.get();
} }
@ -123,7 +122,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
bo.setIsSequel(Boolean.TRUE); bo.setIsSequel(Boolean.TRUE);
CreateUploadUrlRespBO respBO = this.breakResume(uploadingMetadata); CreateUploadUrlRespBO respBO = this.breakResume(uploadingMetadata);
if(!isSelf){ if (!isSelf) {
// 3.其他用户上传过未完成断点续传新增文件元数据 // 3.其他用户上传过未完成断点续传新增文件元数据
// 插入自己的元数据 // 插入自己的元数据
BeanUtils.copyProperties(uploadingMetadata, saveDTO); BeanUtils.copyProperties(uploadingMetadata, saveDTO);
@ -134,9 +133,9 @@ public class StorageEngineServiceImpl implements StorageEngineService {
FileMetadataInfoVo metadataInfoVo = metadataRepository.save(saveDTO); FileMetadataInfoVo metadataInfoVo = metadataRepository.save(saveDTO);
return this.buildResult(metadataInfoVo, respBO.getParts(), respBO.getPartCount(), Boolean.FALSE); return this.buildResult(metadataInfoVo, respBO.getParts(), respBO.getPartCount(), Boolean.FALSE);
}else{ } else {
// 2.当前用户上传过未完成断点续传 // 2.当前用户上传过未完成断点续传
if(CollUtil.isNotEmpty(respBO.getParts()) && !respBO.getUploadTaskId().equals(uploadingMetadata.getUploadTaskId())){ if (CollUtil.isNotEmpty(respBO.getParts()) && !respBO.getUploadTaskId().equals(uploadingMetadata.getUploadTaskId())) {
// 原uploadTaskId失效时同时更新原记录 // 原uploadTaskId失效时同时更新原记录
uploadingMetadata.setUploadTaskId(respBO.getUploadTaskId()); uploadingMetadata.setUploadTaskId(respBO.getUploadTaskId());
FileMetadataInfoUpdateDTO updateDTO = new FileMetadataInfoUpdateDTO(); FileMetadataInfoUpdateDTO updateDTO = new FileMetadataInfoUpdateDTO();
@ -148,7 +147,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
return this.buildResult(uploadingMetadata, respBO.getParts(), respBO.getPartCount(), Boolean.FALSE); return this.buildResult(uploadingMetadata, respBO.getParts(), respBO.getPartCount(), Boolean.FALSE);
} }
}else{ } else {
// 4.从未上传过下发上传链接新增文件元数据 // 4.从未上传过下发上传链接新增文件元数据
bo.setFileMd5(fileMd5); bo.setFileMd5(fileMd5);
@ -259,7 +258,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
* @return {@link Boolean} * @return {@link Boolean}
*/ */
@Override @Override
public CompleteResultVo complete(String fileKey, List<String> partMd5List,String userId) { public CompleteResultVo complete(String fileKey, List<String> partMd5List, String userId) {
CompleteResultVo completeResultVo = new CompleteResultVo(); CompleteResultVo completeResultVo = new CompleteResultVo();
@ -271,24 +270,24 @@ public class StorageEngineServiceImpl implements StorageEngineService {
FileMetadataInfoVo metadata = metadataRepository.one(searchDto); FileMetadataInfoVo metadata = metadataRepository.one(searchDto);
if(metadata == null){ if (metadata == null) {
log.error(fileKey+MinioPlusErrorCode.FILE_EXIST_FAILED.getMessage()); log.error(fileKey + MinioPlusErrorCode.FILE_EXIST_FAILED.getMessage());
throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED.getCode(),fileKey+MinioPlusErrorCode.FILE_EXIST_FAILED.getMessage()); throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED.getCode(), fileKey + MinioPlusErrorCode.FILE_EXIST_FAILED.getMessage());
} }
if(Boolean.TRUE.equals(metadata.getIsFinished())){ if (Boolean.TRUE.equals(metadata.getIsFinished())) {
// 如果文件已上传完成直接返回true不进行合并 // 如果文件已上传完成直接返回true不进行合并
completeResultVo.setIsComplete(true); completeResultVo.setIsComplete(true);
return completeResultVo; return completeResultVo;
} }
if(metadata.getStorageBucket().equals(StorageBucketEnums.IMAGE.getCode())){ if (metadata.getStorageBucket().equals(StorageBucketEnums.IMAGE.getCode())) {
// 图片时生成图片的上传链接 // 图片时生成图片的上传链接
List<FileCheckResultVo.Part> partList = new ArrayList<>(); List<FileCheckResultVo.Part> partList = new ArrayList<>();
FileCheckResultVo.Part part = new FileCheckResultVo.Part(); FileCheckResultVo.Part part = new FileCheckResultVo.Part();
part.setUploadId(metadata.getFileKey()); part.setUploadId(metadata.getFileKey());
part.setUrl("/storage/upload/image/"+metadata.getFileKey()); part.setUrl("/storage/upload/image/" + metadata.getFileKey());
part.setStartPosition(0L); part.setStartPosition(0L);
part.setEndPosition(metadata.getFileSize()); part.setEndPosition(metadata.getFileSize());
partList.add(part); partList.add(part);
@ -316,7 +315,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
searchDto.setFileMd5(metadata.getFileMd5()); searchDto.setFileMd5(metadata.getFileMd5());
searchDto.setIsFinished(false); searchDto.setIsFinished(false);
List<FileMetadataInfoVo> others = metadataRepository.list(searchDto); List<FileMetadataInfoVo> others = metadataRepository.list(searchDto);
if(CollUtil.isNotEmpty(others)){ if (CollUtil.isNotEmpty(others)) {
for (FileMetadataInfoVo other : others) { for (FileMetadataInfoVo other : others) {
updateDTO = new FileMetadataInfoUpdateDTO(); updateDTO = new FileMetadataInfoUpdateDTO();
updateDTO.setId(other.getId()); updateDTO.setId(other.getId());
@ -325,8 +324,8 @@ public class StorageEngineServiceImpl implements StorageEngineService {
metadataRepository.update(updateDTO); metadataRepository.update(updateDTO);
} }
} }
}else{ } else {
if(!metadata.getUploadTaskId().equals(completeResultVo.getUploadTaskId())){ if (!metadata.getUploadTaskId().equals(completeResultVo.getUploadTaskId())) {
FileMetadataInfoUpdateDTO updateDTO = new FileMetadataInfoUpdateDTO(); FileMetadataInfoUpdateDTO updateDTO = new FileMetadataInfoUpdateDTO();
updateDTO.setId(metadata.getId()); updateDTO.setId(metadata.getId());
updateDTO.setUploadTaskId(completeResultVo.getUploadTaskId()); updateDTO.setUploadTaskId(completeResultVo.getUploadTaskId());
@ -354,7 +353,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
saveDto.setFileMimeType(metadata.getFileMimeType()); saveDto.setFileMimeType(metadata.getFileMimeType());
saveDto.setIsPreview(metadata.getIsPreview()); saveDto.setIsPreview(metadata.getIsPreview());
Boolean isCreateFile = createFile(saveDto,file); Boolean isCreateFile = createFile(saveDto, file);
FileMetadataInfoUpdateDTO updateDTO = new FileMetadataInfoUpdateDTO(); FileMetadataInfoUpdateDTO updateDTO = new FileMetadataInfoUpdateDTO();
updateDTO.setId(metadata.getId()); updateDTO.setId(metadata.getId());
@ -364,8 +363,8 @@ public class StorageEngineServiceImpl implements StorageEngineService {
return isCreateFile; return isCreateFile;
}catch(Exception e){ } catch (Exception e) {
log.error(MinioPlusErrorCode.FILE_UPLOAD_FAILED.getMessage(),e); log.error(MinioPlusErrorCode.FILE_UPLOAD_FAILED.getMessage(), e);
throw new MinioPlusException(MinioPlusErrorCode.FILE_UPLOAD_FAILED); throw new MinioPlusException(MinioPlusErrorCode.FILE_UPLOAD_FAILED);
} }
@ -376,14 +375,14 @@ public class StorageEngineServiceImpl implements StorageEngineService {
FileMetadataInfoVo metadata = getFileMetadataInfo(fileKey, userId); FileMetadataInfoVo metadata = getFileMetadataInfo(fileKey, userId);
try{ try {
// 文件权限校验元数据为空或者当前登录用户不是文件所有者时抛出异常 // 文件权限校验元数据为空或者当前登录用户不是文件所有者时抛出异常
this.authentication(metadata, fileKey, userId); this.authentication(metadata, fileKey, userId);
return minioS3Client.getDownloadUrl(metadata.getFileName(),metadata.getFileMimeType(),metadata.getStorageBucket(),metadata.getStoragePath() + "/"+ metadata.getFileMd5()); return minioS3Client.getDownloadUrl(metadata.getFileName(), metadata.getFileMimeType(), metadata.getStorageBucket(), metadata.getStoragePath() + "/" + metadata.getFileMd5());
}catch(Exception e){ } catch (Exception e) {
// 打印日志 // 打印日志
log.error(e.getMessage(),e); log.error(e.getMessage(), e);
// 任何异常统一返回给前端文件不存在 // 任何异常统一返回给前端文件不存在
throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED); throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED);
} }
@ -394,15 +393,15 @@ public class StorageEngineServiceImpl implements StorageEngineService {
FileMetadataInfoVo metadata = getFileMetadataInfo(fileKey, userId); FileMetadataInfoVo metadata = getFileMetadataInfo(fileKey, userId);
try{ try {
// 文件权限校验元数据为空或者当前登录用户不是文件所有者时抛出异常 // 文件权限校验元数据为空或者当前登录用户不是文件所有者时抛出异常
this.authentication(metadata, fileKey, userId); this.authentication(metadata, fileKey, userId);
return minioS3Client.getPreviewUrl(metadata.getFileMimeType(),metadata.getStorageBucket(),metadata.getStoragePath() + "/"+ metadata.getFileMd5()); return minioS3Client.getPreviewUrl(metadata.getFileMimeType(), metadata.getStorageBucket(), metadata.getStoragePath() + "/" + metadata.getFileMd5());
}catch(Exception e){ } catch (Exception e) {
// 打印日志 // 打印日志
log.error(e.getMessage(),e); log.error(e.getMessage(), e);
// 任何异常统一返回给前端文件不存在 // 任何异常统一返回给前端文件不存在
throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED); throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED);
} }
@ -413,48 +412,60 @@ public class StorageEngineServiceImpl implements StorageEngineService {
FileMetadataInfoVo metadata = getFileMetadataInfo(fileKey, userId); FileMetadataInfoVo metadata = getFileMetadataInfo(fileKey, userId);
try{ try {
// 文件权限校验元数据为空或者当前登录用户不是文件所有者时抛出异常 // 文件权限校验元数据为空或者当前登录用户不是文件所有者时抛出异常
this.authentication(metadata, fileKey, userId); this.authentication(metadata, fileKey, userId);
// 判断是否存在缩略图设置桶名称 // 生成缩略图
String bucketName = Boolean.TRUE.equals(metadata.getIsPreview()) ? StorageBucketEnums.IMAGE_PREVIEW.getCode() : metadata.getStorageBucket(); String bucketName = generatePreviewImage(metadata);
// 创建图片预览地址 // 创建图片预览地址
return minioS3Client.getPreviewUrl(metadata.getFileMimeType(),bucketName,metadata.getStoragePath() + "/"+ metadata.getFileMd5()); return minioS3Client.getPreviewUrl(metadata.getFileMimeType(), bucketName, metadata.getStoragePath() + "/" + metadata.getFileMd5());
} catch (Exception e) {
}catch(Exception e){
// 打印日志 // 打印日志
log.error(e.getMessage(),e); log.error(e.getMessage(), e);
// 任何异常统一返回给前端文件不存在 // 任何异常统一返回给前端文件不存在
throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED); throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED);
} }
} }
/**
* 文件元数据
*
* @param metadata 文件元数据
* @return 缩略图桶路径
* @author <a href="mailto:tianxiang.deng@foxmail.com">BaldHead</a>
* @since 2024-06-14 14:44:52
*/
private String generatePreviewImage(FileMetadataInfoVo metadata) {
try {
if (Boolean.FALSE.equals(metadata.getIsPreview())) {
// 获取原图的bytes
byte[] imageOriginBytes = minioS3Client.getObject(StorageBucketEnums.IMAGE.getCode(), metadata.getStoragePath() + "/" + metadata.getFileMd5());
// 压缩缩略图
ByteArrayOutputStream largeImage = CommonUtil.resizeImage(new ByteArrayInputStream(imageOriginBytes), properties.getThumbnail().getSize());
byte[] largeImageBytes = largeImage.toByteArray();
minioS3Client.putObject(StorageBucketEnums.IMAGE_PREVIEW.getCode(), CommonUtil.getObjectName(metadata.getFileMd5()), new ByteArrayInputStream(largeImageBytes), largeImageBytes.length, metadata.getFileMimeType());
return StorageBucketEnums.IMAGE_PREVIEW.getCode();
}
} catch (Exception e) {
// 打印日志
log.error(e.getMessage(), e);
// 任何异常统一返回给前端文件不存在
throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED);
}
return null;
}
@Override @Override
public Boolean createFile(FileMetadataInfoSaveDTO saveDTO, byte[] fileBytes) { public Boolean createFile(FileMetadataInfoSaveDTO saveDTO, byte[] fileBytes) {
// 写入文件 // 写入文件
minioS3Client.putObject(saveDTO.getStorageBucket(), CommonUtil.getObjectName(saveDTO.getFileMd5()), new ByteArrayInputStream(fileBytes), saveDTO.getFileSize(), saveDTO.getFileMimeType()); minioS3Client.putObject(saveDTO.getStorageBucket(), CommonUtil.getObjectName(saveDTO.getFileMd5()), new ByteArrayInputStream(fileBytes), saveDTO.getFileSize(), saveDTO.getFileMimeType());
// 判断是否生成缩略图
if(Boolean.TRUE.equals(saveDTO.getIsPreview())){
try{
ByteArrayOutputStream largeImage = CommonUtil.resizeImage(new ByteArrayInputStream(fileBytes), properties.getThumbnail().getSize());
byte[] largeImageBytes = largeImage.toByteArray();
minioS3Client.putObject(StorageBucketEnums.IMAGE_PREVIEW.getCode(), CommonUtil.getObjectName(saveDTO.getFileMd5()), new ByteArrayInputStream(largeImageBytes), largeImageBytes.length, saveDTO.getFileMimeType());
}catch(Exception e){
log.error(MinioPlusErrorCode.FILE_PREVIEW_WRITE_FAILED.getMessage(),e);
throw new MinioPlusException(MinioPlusErrorCode.FILE_PREVIEW_WRITE_FAILED);
}
}
return true; return true;
} }
@Override @Override
public Pair<FileMetadataInfoVo,byte[]> read(String fileKey) { public Pair<FileMetadataInfoVo, byte[]> read(String fileKey) {
// 查询文件元数据 // 查询文件元数据
FileMetadataInfoDTO fileMetadataInfo = new FileMetadataInfoDTO(); FileMetadataInfoDTO fileMetadataInfo = new FileMetadataInfoDTO();
@ -468,7 +479,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
// 读取流 // 读取流
byte[] fileBytes = minioS3Client.getObject(fileMetadataInfoVo.getStorageBucket(), fileMetadataInfoVo.getStoragePath() + "/" + fileMetadataInfoVo.getFileMd5()); byte[] fileBytes = minioS3Client.getObject(fileMetadataInfoVo.getStorageBucket(), fileMetadataInfoVo.getStoragePath() + "/" + fileMetadataInfoVo.getFileMd5());
return Pair.of(fileMetadataInfoVo,fileBytes); return Pair.of(fileMetadataInfoVo, fileBytes);
} }
@Override @Override
@ -501,7 +512,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
return true; return true;
} }
private void remove(FileMetadataInfoVo metadata){ private void remove(FileMetadataInfoVo metadata) {
// 删除元数据信息 // 删除元数据信息
metadataRepository.remove(metadata.getId()); metadataRepository.remove(metadata.getId());
@ -509,10 +520,10 @@ public class StorageEngineServiceImpl implements StorageEngineService {
fileMetadataInfo.setFileMd5(metadata.getFileMd5()); fileMetadataInfo.setFileMd5(metadata.getFileMd5());
List<FileMetadataInfoVo> metadataList = metadataRepository.list(fileMetadataInfo); List<FileMetadataInfoVo> metadataList = metadataRepository.list(fileMetadataInfo);
if(CollUtil.isEmpty(metadataList)){ if (CollUtil.isEmpty(metadataList)) {
// 当不存在任何该MD5值的文件元数据时删除物理文件 // 当不存在任何该MD5值的文件元数据时删除物理文件
minioS3Client.removeObject(metadata.getStorageBucket(), metadata.getStoragePath() + "/" + metadata.getFileMd5()); minioS3Client.removeObject(metadata.getStorageBucket(), metadata.getStoragePath() + "/" + metadata.getFileMd5());
if(Boolean.TRUE.equals(metadata.getIsPreview())){ if (Boolean.TRUE.equals(metadata.getIsPreview())) {
// 当存在缩略图时同步删除缩略图 // 当存在缩略图时同步删除缩略图
minioS3Client.removeObject(StorageBucketEnums.IMAGE_PREVIEW.getCode(), metadata.getStoragePath() + "/" + metadata.getFileMd5()); minioS3Client.removeObject(StorageBucketEnums.IMAGE_PREVIEW.getCode(), metadata.getStoragePath() + "/" + metadata.getFileMd5());
} }
@ -522,6 +533,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
/** /**
* 根据用户取得文件元数据信息 * 根据用户取得文件元数据信息
* 当userId匹配时直接返回不匹配时检查是否存在公有元数据 * 当userId匹配时直接返回不匹配时检查是否存在公有元数据
*
* @param fileKey 文件KEY * @param fileKey 文件KEY
* @param userId 用户主键 * @param userId 用户主键
* @return 文件元数据信息 * @return 文件元数据信息
@ -550,14 +562,14 @@ public class StorageEngineServiceImpl implements StorageEngineService {
* @param fileKey 文件key * @param fileKey 文件key
* @param userId 用户主键 * @param userId 用户主键
*/ */
private void authentication(FileMetadataInfoVo metadata, String fileKey, String userId){ private void authentication(FileMetadataInfoVo metadata, String fileKey, String userId) {
if (null == metadata) { if (null == metadata) {
throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED.getCode(), fileKey + MinioPlusErrorCode.FILE_EXIST_FAILED.getMessage()); throw new MinioPlusException(MinioPlusErrorCode.FILE_EXIST_FAILED.getCode(), fileKey + MinioPlusErrorCode.FILE_EXIST_FAILED.getMessage());
} }
// 元数据信息存在判断权限 // 元数据信息存在判断权限
if(Boolean.TRUE.equals(metadata.getIsPrivate()) && !userId.equals(metadata.getCreateUser())){ if (Boolean.TRUE.equals(metadata.getIsPrivate()) && !userId.equals(metadata.getCreateUser())) {
throw new MinioPlusException(MinioPlusErrorCode.FILE_PERMISSION_CHECK_FAILED.getCode(), fileKey + "用户"+userId+MinioPlusErrorCode.FILE_PERMISSION_CHECK_FAILED.getMessage()); throw new MinioPlusException(MinioPlusErrorCode.FILE_PERMISSION_CHECK_FAILED.getCode(), fileKey + "用户" + userId + MinioPlusErrorCode.FILE_PERMISSION_CHECK_FAILED.getMessage());
} }
} }
@ -586,10 +598,10 @@ public class StorageEngineServiceImpl implements StorageEngineService {
* @param partNumber 块号 * @param partNumber 块号
* @return {@link FileCheckResultVo.Part} * @return {@link FileCheckResultVo.Part}
*/ */
private FileCheckResultVo.Part buildResultPart(String bucketName,String objectName,String uploadId, Long fileSize, long start, Integer partNumber) { private FileCheckResultVo.Part buildResultPart(String bucketName, String objectName, String uploadId, Long fileSize, long start, Integer partNumber) {
// 计算起始位置 // 计算起始位置
long end = Math.min(start + properties.getPart().getSize(), fileSize); long end = Math.min(start + properties.getPart().getSize(), fileSize);
String uploadUrl = minioS3Client.getUploadObjectUrl(bucketName, objectName, uploadId,String.valueOf(partNumber)); String uploadUrl = minioS3Client.getUploadObjectUrl(bucketName, objectName, uploadId, String.valueOf(partNumber));
FileCheckResultVo.Part part = new FileCheckResultVo.Part(); FileCheckResultVo.Part part = new FileCheckResultVo.Part();
part.setUploadId(uploadId); part.setUploadId(uploadId);
// 上传地址 // 上传地址
@ -603,6 +615,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
/** /**
* 断点续传-创建断点的URL * 断点续传-创建断点的URL
*
* @param fileMetadataVo 文件元数据信息 * @param fileMetadataVo 文件元数据信息
* @return CreateUploadUrlRespBO 分片结果 * @return CreateUploadUrlRespBO 分片结果
*/ */
@ -644,7 +657,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
// 丢失的块号-断点续传时必传 // 丢失的块号-断点续传时必传
bo.setMissPartNum(missingNumbers); bo.setMissPartNum(missingNumbers);
if(missingNumbers.size() != chunkNum){ if (missingNumbers.size() != chunkNum) {
// 任务id任务id可能会失效 // 任务id任务id可能会失效
bo.setUploadId(fileMetadataVo.getUploadTaskId()); bo.setUploadId(fileMetadataVo.getUploadTaskId());
} }
@ -665,6 +678,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
/** /**
* 合并分片 * 合并分片
*
* @param metadataInfo 文件元数据信息 * @param metadataInfo 文件元数据信息
* @param partMd5List 分片集合 * @param partMd5List 分片集合
* @return 合并结果 * @return 合并结果
@ -676,12 +690,12 @@ public class StorageEngineServiceImpl implements StorageEngineService {
// 获取所有的分片信息 // 获取所有的分片信息
ListParts listParts = this.buildResultPart(metadataInfo); ListParts listParts = this.buildResultPart(metadataInfo);
List<Integer> missingNumbers =new ArrayList<>(); List<Integer> missingNumbers = new ArrayList<>();
// 分块数量 // 分块数量
Integer chunkNum = metadataInfo.getPartNumber(); Integer chunkNum = metadataInfo.getPartNumber();
if(partMd5List==null || chunkNum != partMd5List.size()){ if (partMd5List == null || chunkNum != partMd5List.size()) {
throw new MinioPlusException(MinioPlusErrorCode.FILE_PART_NUM_CHECK_FAILED); throw new MinioPlusException(MinioPlusErrorCode.FILE_PART_NUM_CHECK_FAILED);
} }
@ -689,16 +703,16 @@ public class StorageEngineServiceImpl implements StorageEngineService {
for (int i = 1; i <= chunkNum; i++) { for (int i = 1; i <= chunkNum; i++) {
boolean findPart = false; boolean findPart = false;
for (ListParts.Part part : listParts.getPartList()) { for (ListParts.Part part : listParts.getPartList()) {
if(part.getPartNumber() == i && CharSequenceUtil.equalsIgnoreCase(part.getEtag(), partMd5List.get(i - 1))){ if (part.getPartNumber() == i && CharSequenceUtil.equalsIgnoreCase(part.getEtag(), partMd5List.get(i - 1))) {
findPart = true; findPart = true;
} }
} }
if(!findPart){ if (!findPart) {
missingNumbers.add(i); missingNumbers.add(i);
} }
} }
if(CollUtil.isNotEmpty(missingNumbers)){ if (CollUtil.isNotEmpty(missingNumbers)) {
CreateUploadUrlReqBO bo = new CreateUploadUrlReqBO(); CreateUploadUrlReqBO bo = new CreateUploadUrlReqBO();
// 文件md5 // 文件md5
bo.setFileMd5(metadataInfo.getFileMd5()); bo.setFileMd5(metadataInfo.getFileMd5());
@ -710,7 +724,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
bo.setIsSequel(Boolean.TRUE); bo.setIsSequel(Boolean.TRUE);
// 丢失的块号-断点续传时必传 // 丢失的块号-断点续传时必传
bo.setMissPartNum(missingNumbers); bo.setMissPartNum(missingNumbers);
if(missingNumbers.size() != chunkNum){ if (missingNumbers.size() != chunkNum) {
// 任务id任务id可能会失效 // 任务id任务id可能会失效
bo.setUploadId(metadataInfo.getUploadTaskId()); bo.setUploadId(metadataInfo.getUploadTaskId());
} }
@ -725,12 +739,12 @@ public class StorageEngineServiceImpl implements StorageEngineService {
completeResultVo.setIsComplete(false); completeResultVo.setIsComplete(false);
completeResultVo.setUploadTaskId(createUploadUrlRespBO.getUploadTaskId()); completeResultVo.setUploadTaskId(createUploadUrlRespBO.getUploadTaskId());
completeResultVo.setPartList(createUploadUrlRespBO.getParts()); completeResultVo.setPartList(createUploadUrlRespBO.getParts());
}else{ } else {
// 合并分块 // 合并分块
boolean writeResponse = minioS3Client.completeMultipartUpload(metadataInfo.getStorageBucket() boolean writeResponse = minioS3Client.completeMultipartUpload(metadataInfo.getStorageBucket()
,listParts.getObjectName() , listParts.getObjectName()
,metadataInfo.getUploadTaskId() , metadataInfo.getUploadTaskId()
,listParts.getPartList() , listParts.getPartList()
); );
completeResultVo.setIsComplete(writeResponse); completeResultVo.setIsComplete(writeResponse);
completeResultVo.setPartList(new ArrayList<>()); completeResultVo.setPartList(new ArrayList<>());
@ -745,7 +759,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
* @param metadataInfo 文件元数据信息 * @param metadataInfo 文件元数据信息
* @return {@link ListParts} 分片任务信息 * @return {@link ListParts} 分片任务信息
*/ */
private ListParts buildResultPart(FileMetadataInfoVo metadataInfo){ private ListParts buildResultPart(FileMetadataInfoVo metadataInfo) {
String objectName = CommonUtil.getObjectName(metadataInfo.getFileMd5()); String objectName = CommonUtil.getObjectName(metadataInfo.getFileMd5());
// 获取所有的分片信息 // 获取所有的分片信息
return minioS3Client.listParts(metadataInfo.getStorageBucket(), objectName, metadataInfo.getPartNumber(), metadataInfo.getUploadTaskId()); return minioS3Client.listParts(metadataInfo.getStorageBucket(), objectName, metadataInfo.getPartNumber(), metadataInfo.getUploadTaskId());
@ -777,7 +791,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
// 开始位置 // 开始位置
long start = (long) (bo.getMissPartNum().get(0) - 1) * properties.getPart().getSize(); long start = (long) (bo.getMissPartNum().get(0) - 1) * properties.getPart().getSize();
for (int partNumber : bo.getMissPartNum()) { for (int partNumber : bo.getMissPartNum()) {
FileCheckResultVo.Part part = this.buildResultPart(bucketName,storagePath, uploadId, bo.getFileSize(), start, partNumber); FileCheckResultVo.Part part = this.buildResultPart(bucketName, storagePath, uploadId, bo.getFileSize(), start, partNumber);
// 更改下一次的开始位置 // 更改下一次的开始位置
start = start + properties.getPart().getSize(); start = start + properties.getPart().getSize();
partList.add(part); partList.add(part);
@ -803,7 +817,7 @@ public class StorageEngineServiceImpl implements StorageEngineService {
FileCheckResultVo.Part part = new FileCheckResultVo.Part(); FileCheckResultVo.Part part = new FileCheckResultVo.Part();
// 图片上传时直接使用fileKey作为uploadId // 图片上传时直接使用fileKey作为uploadId
part.setUploadId(fileKey); part.setUploadId(fileKey);
part.setUrl("/storage/upload/image/"+fileKey); part.setUrl("/storage/upload/image/" + fileKey);
part.setStartPosition(0L); part.setStartPosition(0L);
part.setEndPosition(bo.getFileSize()); part.setEndPosition(bo.getFileSize());
partList.add(part); partList.add(part);