buhuazhen
8 天以前 a8df571a0d7da69764506fc6a1b5b6da334645b1
ruoyi-common/src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java
@@ -2,29 +2,32 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Iterables;
import com.ruoyi.basic.entity.StorageAttachment;
import com.ruoyi.basic.entity.StorageBlob;
import com.ruoyi.basic.entity.dto.SimpleStorageDto;
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.config.MinioConfig;
import com.ruoyi.common.constant.Constants;
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.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.MinioUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
 * <p>
@@ -46,37 +49,88 @@
    @Autowired
    private MinioUtils minioUtils;
    @Getter
    @Value("${minio.default-bucket}")
    private String defaultBucket;
    @Override
    public List<StorageBlobDTO> updateStorageBlobs(List<MultipartFile> files, String bucketName) {
    public List<StorageBlobDTO> updateStorageBlobs(List<MultipartFile> files, String bucketName, Long type) {
        // 若没传入bucketName,则使用默认bucketName
        if (StringUtils.isEmpty(bucketName)) {
            bucketName  = minioUtils.getDefaultBucket();
            bucketName = minioUtils.getDefaultBucket();
        }
        List<StorageBlobDTO> storageBlobDTOs = new ArrayList<>();
        for (MultipartFile file : files) {
            try {
                MinioResult res = minioUtils.upload(bucketName, file, false);
                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));
                // 插入数据库
                storageBlobMapper.insert(dto);
                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("minio文件上传异常:" +  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<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);
        }
    }
    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
@@ -85,20 +139,65 @@
                .eq(StorageAttachment::getRecordId, attachment.getRecordId())
                .eq(StorageAttachment::getRecordType, attachment.getRecordType())
                .eq(StorageAttachment::getName, attachment.getName()));
        List<Long> ids = attachments.stream().map(StorageAttachment::getStorageBlobId).toList();
        List<StorageBlob> storageBlobs = storageBlobMapper.selectList(new LambdaQueryWrapper<StorageBlob>()
                .in(StorageBlob::getId, ids));
        List<Long> ids = attachments.stream()
                .map(StorageAttachment::getStorageBlobId)
                .collect(Collectors.toList());
        List<StorageBlob> storageBlobs = new ArrayList<>();
        if (!ids.isEmpty()) {
            // 只在ID列表非空时执行查询
            storageBlobs = storageBlobMapper.selectList(
                    new LambdaQueryWrapper<StorageBlob>().in(StorageBlob::getId, ids)
            );
        }
        // 移除MinIO中的文件
        if (!storageBlobs.isEmpty()) {
            for (StorageBlob storageBlob : storageBlobs) {
                // 移除桶内文件
                minioUtils.removeObjectsResult(storageBlob.getBucketName(), storageBlob.getBucketName());
                minioUtils.removeObjectsResult(storageBlob.getBucketName(), storageBlob.getBucketFilename());
            }
        }
        // 删除数据库记录
        if (!ids.isEmpty()) {
            return storageBlobMapper.delete(new QueryWrapper<StorageBlob>().lambda().in(StorageBlob::getId, ids));
            return storageBlobMapper.delete(
                    new QueryWrapper<StorageBlob>().lambda().in(StorageBlob::getId, ids)
            );
        }
        return 0;
    }
    @Override
    public List<SimpleStorageDto> findStorageByIds(List<Long> ids, String bucketName) {
        if (ids == null || ids.isEmpty()) {
            return List.of();
        }
        return storageBlobMapper.selectByIds(ids).parallelStream().map(it -> {
            SimpleStorageDto dto = new SimpleStorageDto(it.getId(), it.getContentType(), it.getOriginalFilename(), it.getCreateTime());
            dto.setUrl(minioUtils.getDownloadUrls(it.getBucketFilename(), bucketName, it.getOriginalFilename(), true));
            dto.setPreviewUrl(minioUtils.getPreviewUrl(it.getBucketFilename(), bucketName, true));
            return dto;
        }).toList();
    }
    @Override
    public Map<Long, List<SimpleStorageDto>> conver(Map<Long, List<Long>> attachMap) {
        if (attachMap == null || attachMap.isEmpty()) {
            return Map.of();
        }
        List<Long> storageBlobIds = attachMap.values().stream().flatMap(Collection::stream).toList();
        if(Iterables.isEmpty(storageBlobIds)){
            return Map.of();
        }
        return 0;
        Map<Long,SimpleStorageDto> storageMap = this.findStorageByIds(storageBlobIds, defaultBucket).stream().collect(Collectors.toMap(SimpleStorageDto::getId,it->it));;
        Map<Long, List<SimpleStorageDto>> finalMap = new HashMap<>();
        attachMap.forEach((k,v)->{
            finalMap.put(k, v.stream().map(storageMap::get).toList());
        });
        return finalMap;
    }
}