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;
|
|
/**
|
* <p>
|
* 通用文件上传的附件信息 服务实现类
|
* </p>
|
*
|
* @author ruoyi
|
* @since 2025-05-29
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class StorageBlobServiceImpl extends ServiceImpl<StorageBlobMapper, StorageBlob> implements StorageBlobService {
|
@Autowired
|
private StorageAttachmentMapper storageAttachmentMapper;
|
|
@Autowired
|
private StorageBlobMapper storageBlobMapper;
|
|
@Autowired
|
private MinioUtils minioUtils;
|
|
@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 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
|
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());
|
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.getBucketFilename());
|
}
|
}
|
|
// 删除数据库记录
|
if (!ids.isEmpty()) {
|
return storageBlobMapper.delete(
|
new QueryWrapper<StorageBlob>().lambda().in(StorageBlob::getId, ids)
|
);
|
}
|
return 0;
|
}
|
}
|