package com.ruoyi.basic.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.entity.StorageAttachment; import com.ruoyi.basic.entity.StorageBlob; import com.ruoyi.basic.entity.dto.StorageBlobDTO; import com.ruoyi.basic.mapper.StorageAttachmentMapper; import com.ruoyi.basic.mapper.StorageBlobMapper; import com.ruoyi.basic.service.StorageBlobService; import com.ruoyi.common.core.domain.MinioResult; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.exception.file.InvalidExtensionException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.file.MinioUtils; import com.ruoyi.common.utils.uuid.IdUtils; import lombok.RequiredArgsConstructor; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; /** *

* 通用文件上传的附件信息 服务实现类 *

* * @author ruoyi * @since 2025-05-29 */ @Service @RequiredArgsConstructor public class StorageBlobServiceImpl extends ServiceImpl implements StorageBlobService { @Autowired private StorageAttachmentMapper storageAttachmentMapper; @Autowired private StorageBlobMapper storageBlobMapper; @Autowired private MinioUtils minioUtils; @Override public List updateStorageBlobs(List files, String bucketName,Long type) { // 若没传入bucketName,则使用默认bucketName if (StringUtils.isEmpty(bucketName)) { bucketName = minioUtils.getDefaultBucket(); } List 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 void validateFileExtension(MultipartFile file) throws InvalidExtensionException { String filename = file.getOriginalFilename(); String extension = FilenameUtils.getExtension(filename).toLowerCase(); List 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); } } 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.setKey(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; } @Override public int deleteStorageBlobs(StorageAttachment attachment) { List attachments = storageAttachmentMapper.selectList(new LambdaQueryWrapper() .eq(StorageAttachment::getRecordId, attachment.getRecordId()) .eq(StorageAttachment::getRecordType, attachment.getRecordType()) .eq(StorageAttachment::getName, attachment.getName())); List ids = attachments.stream() .map(StorageAttachment::getStorageBlobId) .collect(Collectors.toList()); List storageBlobs = new ArrayList<>(); if (!ids.isEmpty()) { // 只在ID列表非空时执行查询 storageBlobs = storageBlobMapper.selectList( new LambdaQueryWrapper().in(StorageBlob::getId, ids) ); } // 移除MinIO中的文件 if (!storageBlobs.isEmpty()) { for (StorageBlob storageBlob : storageBlobs) { minioUtils.removeObjectsResult(storageBlob.getBucketName(), storageBlob.getBucketFilename()); } } // 删除数据库记录 if (!ids.isEmpty()) { return storageBlobMapper.delete( new QueryWrapper().lambda().in(StorageBlob::getId, ids) ); } return 0; } }