This commit is contained in:
ovo 2024-12-07 22:56:18 +08:00
parent ba3c78baeb
commit 5e5a51425c
5 changed files with 280 additions and 3 deletions

14
pom.xml
View File

@ -160,6 +160,20 @@
<artifactId>aspectjweaver</artifactId>
</dependency>
<!-- MinIO -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.7</version>
</dependency>
<!-- 文件处理 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,32 @@
package com.guwan.backend.config;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
private String endpoint;
private String accessKey;
private String secretKey;
private Bucket bucket;
@Data
public static class Bucket {
private String files;
private String images;
}
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}

View File

@ -0,0 +1,159 @@
package com.guwan.backend.util;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
@RequiredArgsConstructor
public class MinioUtil {
private final MinioClient minioClient;
/**
* 创建存储桶
*/
public void createBucket(String bucketName) {
try {
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
} catch (Exception e) {
log.error("创建存储桶失败", e);
throw new RuntimeException("创建存储桶失败", e);
}
}
/**
* 上传文件
*/
public String uploadFile(String bucketName, MultipartFile file) {
try {
String fileName = generateFileName(file.getOriginalFilename());
InputStream inputStream = file.getInputStream();
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build()
);
return fileName;
} catch (Exception e) {
log.error("上传文件失败", e);
throw new RuntimeException("上传文件失败", e);
}
}
/**
* 上传Base64图片
*/
public String uploadBase64Image(String bucketName, String base64Image, String folder) {
try {
String[] parts = base64Image.split(",");
String imageData = parts[1];
byte[] bytes = Base64.getDecoder().decode(imageData);
String fileName = folder + "/" + UUID.randomUUID() + ".jpg";
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.stream(inputStream, bytes.length, -1)
.contentType("image/jpeg")
.build()
);
return fileName;
} catch (Exception e) {
log.error("上传Base64图片失败", e);
throw new RuntimeException("上传Base64图片失败", e);
}
}
/**
* 删除文件
*/
public void deleteFile(String bucketName, String fileName) {
try {
minioClient.removeObject(
RemoveObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.build()
);
} catch (Exception e) {
log.error("删除文件失败", e);
throw new RuntimeException("删除文件失败", e);
}
}
/**
* 批量删除文件
*/
public void deleteFiles(String bucketName, List<String> fileNames) {
try {
List<DeleteObject> objects = fileNames.stream()
.map(DeleteObject::new)
.toList();
Iterable<Result<DeleteError>> results = minioClient.removeObjects(
RemoveObjectsArgs.builder()
.bucket(bucketName)
.objects(objects)
.build()
);
for (Result<DeleteError> result : results) {
DeleteError error = result.get();
log.error("删除文件失败: {}", error.message());
}
} catch (Exception e) {
log.error("批量删除文件失败", e);
throw new RuntimeException("批量删除文件失败", e);
}
}
/**
* 获取文件访问URL
*/
public String getFileUrl(String bucketName, String fileName) {
try {
return minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(fileName)
.expiry(7, TimeUnit.DAYS)
.build()
);
} catch (Exception e) {
log.error("获取文件访问URL失败", e);
throw new RuntimeException("获取文件访问URL失败", e);
}
}
/**
* 生成文件名
*/
private String generateFileName(String originalFilename) {
String extension = FilenameUtils.getExtension(originalFilename);
return UUID.randomUUID() + "." + extension;
}
}

View File

@ -74,9 +74,14 @@ jwt:
aliyun:
sms:
# MinIO配置
minio:
endpoint: http://localhost:9000
accessKey: minioadmin
secretKey: minioadmin
bucket:
files: files # 文件桶
images: images # 图片桶
# 文件上传配置
file:

View File

@ -0,0 +1,67 @@
package com.guwan.backend.util;
import com.guwan.backend.config.MinioConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockMultipartFile;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class MinioUtilTest {
@Autowired
private MinioUtil minioUtil;
@Autowired
private MinioConfig minioConfig;
@Test
void testUploadAndDeleteFile() {
// 创建测试文件
String content = "test content";
MockMultipartFile file = new MockMultipartFile(
"test.txt",
"test.txt",
"text/plain",
content.getBytes(StandardCharsets.UTF_8)
);
// 上传文件
String fileName = minioUtil.uploadFile(minioConfig.getBucket().getFiles(), file);
assertNotNull(fileName);
// 获取文件URL
String url = minioUtil.getFileUrl(minioConfig.getBucket().getFiles(), fileName);
assertNotNull(url);
assertTrue(url.contains(fileName));
// 删除文件
minioUtil.deleteFile(minioConfig.getBucket().getFiles(), fileName);
}
@Test
void testUploadBase64Image() {
// 创建Base64图片
String base64Image = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABmX/9k=";
// 上传图片
String fileName = minioUtil.uploadBase64Image(
minioConfig.getBucket().getImages(),
base64Image,
"test"
);
assertNotNull(fileName);
// 获取图片URL
String url = minioUtil.getFileUrl(minioConfig.getBucket().getImages(), fileName);
assertNotNull(url);
assertTrue(url.contains(fileName));
// 删除图片
minioUtil.deleteFile(minioConfig.getBucket().getImages(), fileName);
}
}