|  |  | 
 |  |  | import com.ruoyi.basic.pojo.StorageAttachment; | 
 |  |  | import com.ruoyi.basic.pojo.StorageBlob; | 
 |  |  | import com.ruoyi.basic.service.StorageBlobService; | 
 |  |  | import com.ruoyi.common.exception.base.BaseException; | 
 |  |  | import com.ruoyi.common.exception.file.InvalidExtensionException; | 
 |  |  | import com.ruoyi.common.utils.DateUtils; | 
 |  |  | import com.ruoyi.common.utils.MinioUtils; | 
 |  |  | 
 |  |  | import com.ruoyi.common.utils.uuid.IdUtils; | 
 |  |  | import com.ruoyi.framework.web.domain.MinioResult; | 
 |  |  | import lombok.RequiredArgsConstructor; | 
 |  |  | import org.apache.commons.io.FilenameUtils; | 
 |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
 |  |  | import org.springframework.stereotype.Service; | 
 |  |  | import org.springframework.util.CollectionUtils; | 
 |  |  | import org.springframework.web.multipart.MultipartFile; | 
 |  |  |  | 
 |  |  | import java.time.LocalDateTime; | 
 |  |  | import java.util.ArrayList; | 
 |  |  | import java.util.Arrays; | 
 |  |  | import java.util.List; | 
 |  |  | import java.util.stream.Collectors; | 
 |  |  |  | 
 |  |  | 
 |  |  |                 dto.setBucketFilename(res.getBucketFileName()); | 
 |  |  |                 dto.setOriginalFilename(res.getOriginalName()); | 
 |  |  |                 dto.setByteSize(file.getSize()); | 
 |  |  |                 dto.setKey(IdUtils.simpleUUID()); | 
 |  |  |                 dto.setResourceKey(IdUtils.simpleUUID()); | 
 |  |  |                 dto.setBucketName(bucketName); | 
 |  |  |                 dto.setCreateTime(DateUtils.getNowDate()); | 
 |  |  |                 dto.setUrl(minioUtils.getPreviewUrl(res.getBucketFileName(), bucketName, false)); | 
 |  |  |                 // 插入数据库 | 
 |  |  |                 storageBlobMapper.insert(dto); | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public List<StorageBlobDTO> updateStorageBlobs(List<MultipartFile> files, String bucketName, Long type) { | 
 |  |  |  | 
 |  |  |         // 若没传入bucketName,则使用默认bucketName | 
 |  |  |         if (StringUtils.isEmpty(bucketName)) { | 
 |  |  |             bucketName = minioUtils.getDefaultBucket(); | 
 |  |  |         } | 
 |  |  |         List<StorageBlobDTO> storageBlobDTOs = new ArrayList<>(); | 
 |  |  |         for (MultipartFile file : files) { | 
 |  |  |             try { | 
 |  |  |                 validateFileExtension(file); | 
 |  |  |  | 
 |  |  |                 MinioResult res = minioUtils.upload(bucketName, file, false); | 
 |  |  |  | 
 |  |  |                 StorageBlobDTO dto = buildStorageBlobDTO(file, res, bucketName, type); | 
 |  |  |  | 
 |  |  |                 storageBlobMapper.insert(dto); | 
 |  |  |                 storageBlobDTOs.add(dto); | 
 |  |  |  | 
 |  |  |             } catch (InvalidExtensionException e) { | 
 |  |  |                 throw new RuntimeException("不支持的文件类型:" + file.getOriginalFilename(), e); | 
 |  |  |             } catch (Exception e) { | 
 |  |  |                 throw new RuntimeException("上传文件失败:" + file.getOriginalFilename(), e); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return storageBlobDTOs; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private StorageBlobDTO buildStorageBlobDTO(MultipartFile file, MinioResult res, String bucketName, Long type) { | 
 |  |  |         StorageBlobDTO dto = new StorageBlobDTO(); | 
 |  |  |         dto.setContentType(file.getContentType()); | 
 |  |  |         dto.setBucketFilename(res.getBucketFileName()); | 
 |  |  |         dto.setOriginalFilename(res.getOriginalName()); | 
 |  |  |         dto.setByteSize(file.getSize()); | 
 |  |  |         dto.setResourceKey(IdUtils.simpleUUID()); | 
 |  |  |         dto.setBucketName(bucketName); | 
 |  |  |         dto.setUrl(minioUtils.getPreviewUrl(res.getBucketFileName(), bucketName, false)); | 
 |  |  |         dto.setDownloadUrl(minioUtils.getDownloadUrl(res.getBucketFileName(), bucketName)); | 
 |  |  |  | 
 |  |  |         if (type != null) { | 
 |  |  |             dto.setType(type); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return dto; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private void validateFileExtension(MultipartFile file) throws InvalidExtensionException { | 
 |  |  |         String filename = file.getOriginalFilename(); | 
 |  |  |         String extension = FilenameUtils.getExtension(filename).toLowerCase(); | 
 |  |  |         List<String> allowedExtensions = Arrays.asList( | 
 |  |  |                 // 图片 | 
 |  |  |                 "jpg", "jpeg", "png", "gif", "bmp", "webp", "tiff", "ico", "svg", | 
 |  |  |  | 
 |  |  |                 // 文档 | 
 |  |  |                 "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "rtf", "md", "csv", "odt", | 
 |  |  |  | 
 |  |  |                 // 视频 | 
 |  |  |                 "mp4", "mov", "avi", "wmv", "flv", "mkv", "webm", "mpeg", "3gp", "MOV", | 
 |  |  |  | 
 |  |  |                 // 音频 | 
 |  |  |                 "mp3", "wav", "ogg", "aac", "flac", "m4a", "wma", "amr", | 
 |  |  |  | 
 |  |  |                 // 压缩包 | 
 |  |  |                 "zip", "rar", "7z", "tar", "gz", "bz2", "xz", | 
 |  |  |  | 
 |  |  |                 // 编程代码文件 | 
 |  |  |                 "java", "py", "js", "ts", "html", "css", "cpp", "c", "cs", "json", "xml", "sql", "yaml", "yml", "sh", "bat", | 
 |  |  |  | 
 |  |  |                 // 安装程序 & 二进制 | 
 |  |  |                 "exe", "apk", "dmg", "msi", "bin", "iso", | 
 |  |  |  | 
 |  |  |                 // 设计类 | 
 |  |  |                 "psd", "ai", "xd", "sketch", "fig" | 
 |  |  |         ); | 
 |  |  |  | 
 |  |  |         if (!allowedExtensions.contains(extension)) { | 
 |  |  |             throw new BaseException("文件类型不被允许:" + extension); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public int deleteStorageBlobs(StorageAttachment attachment) { | 
 |  |  |         List<StorageAttachment> attachments = storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>() | 
 |  |  |                 .eq(StorageAttachment::getRecordId, attachment.getRecordId()) | 
 |  |  |                 .eq(StorageAttachment::getRecordType, attachment.getRecordType()) | 
 |  |  |                 .eq(StorageAttachment::getName, attachment.getName())); | 
 |  |  |         List<Long> ids = attachments.stream().map(StorageAttachment::getStorageBlobId).collect(Collectors.toList()); | 
 |  |  |         if(CollectionUtils.isEmpty(ids)){ | 
 |  |  |             return 0; | 
 |  |  |         } | 
 |  |  |         List<StorageBlob> storageBlobs = storageBlobMapper.selectList(new LambdaQueryWrapper<StorageBlob>() | 
 |  |  |                 .in(StorageBlob::getId, ids)); | 
 |  |  |         if (!storageBlobs.isEmpty()) { |