refactor(file-upload): 移除MinIO,新增RustFS存储支持
- 删除MinIO相关实现及配置 - 新增RustFS配置类,支持RustFS客户端初始化 - 新增RustFS存储服务实现,实现文件上传接口 - FileController添加日志打印上传异常信息 - pom.xml替换MinIO依赖为AWS SDK S3依赖 - 代码结构优化,提升文件上传模块的扩展性和稳定性
This commit is contained in:
parent
22075e0f63
commit
17bc951289
|
|
@ -20,6 +20,7 @@ import jakarta.annotation.Resource;
|
|||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
|
@ -33,6 +34,7 @@ import java.util.List;
|
|||
/**
|
||||
* 文件管理相关接口
|
||||
**/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/file")
|
||||
public class FileController extends BaseController {
|
||||
|
|
@ -58,6 +60,7 @@ public class FileController extends BaseController {
|
|||
String url = fileUploadService.upload(buildFilePath(fileType), file);
|
||||
return ApiResult.success(new FileUploadVO(0L, fileName, url));
|
||||
} catch (Exception ex) {
|
||||
log.error("上传文件失败", ex);
|
||||
throw new NflgException(STATE.BusinessError, "上传文件失败:" + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
|
@ -94,18 +93,6 @@
|
|||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>cn.hutool</groupId>-->
|
||||
<!-- <artifactId>hutool-all</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.baomidou</groupId>-->
|
||||
<!-- <artifactId>mybatis-plus-jsqlparser</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.mysql</groupId>-->
|
||||
<!-- <artifactId>mysql-connector-j</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
|
|
@ -126,9 +113,9 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>8.5.17</version>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3</artifactId>
|
||||
<version>2.39.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
package com.nflg.wms.starter.config;
|
||||
|
||||
import io.minio.BucketExistsArgs;
|
||||
import io.minio.MakeBucketArgs;
|
||||
import io.minio.MinioClient;
|
||||
import io.minio.SetBucketPolicyArgs;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "file.upload.type", havingValue = "minio")
|
||||
public class MinIOConfig {
|
||||
|
||||
@Value("${minio.endpoint}")
|
||||
private String endpoint;
|
||||
|
||||
@Value("${minio.access-key}")
|
||||
private String accessKey;
|
||||
|
||||
@Value("${minio.secret-key}")
|
||||
private String secretKey;
|
||||
|
||||
@Value("${minio.bucket-name}")
|
||||
private String bucketName;
|
||||
|
||||
private MinioClient client;
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public MinioClient initMinioClient() throws Exception{
|
||||
client= MinioClient.builder()
|
||||
.endpoint(endpoint)
|
||||
.credentials(accessKey, secretKey)
|
||||
.build();
|
||||
// 自动创建 bucket(如果不存在)
|
||||
if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
|
||||
client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||
}
|
||||
String policyJsonString = """
|
||||
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":"*","Action":"s3:GetObject","Resource":"arn:aws:s3:::%s/*"}]}""".formatted(bucketName);
|
||||
client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policyJsonString).build());
|
||||
return client;
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
try {
|
||||
client.close();
|
||||
} catch (Exception e) {
|
||||
log.error("MinIO 销毁出错", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.nflg.wms.starter.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
|
||||
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "file.upload.type", havingValue = "rustfs")
|
||||
public class RustFSConfig {
|
||||
|
||||
@Value("${rustfs.endpoint}")
|
||||
private String endpoint;
|
||||
|
||||
@Value("${rustfs.access-key}")
|
||||
private String accessKey;
|
||||
|
||||
@Value("${rustfs.secret-key}")
|
||||
private String secretKey;
|
||||
|
||||
@Bean
|
||||
public S3Client s3Client() {
|
||||
return S3Client.builder()
|
||||
.endpointOverride(URI.create(endpoint))
|
||||
.region(Region.US_EAST_1) // 自建服务通常可设为任意值
|
||||
.credentialsProvider(StaticCredentialsProvider.create(
|
||||
AwsBasicCredentials.create(accessKey, secretKey)))
|
||||
.forcePathStyle(true) // RustFS 必须启用 Path-Style
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
package com.nflg.wms.starter.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nflg.wms.starter.service.FileUploadService;
|
||||
import io.minio.MinioClient;
|
||||
import io.minio.PutObjectArgs;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "file.upload.type", havingValue = "minio")
|
||||
public class MinIOServiceImpl implements FileUploadService {
|
||||
|
||||
@Value("${minio.bucket-name}")
|
||||
private String bucketName;
|
||||
|
||||
@Value("${minio.endpoint}")
|
||||
private String domain;
|
||||
|
||||
@Resource
|
||||
private MinioClient minioClient;
|
||||
|
||||
@Override
|
||||
public String upload(String filePath, MultipartFile file) throws Exception {
|
||||
return upload(filePath, file.getInputStream(), file.getContentType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(String filePath, InputStream stream, String contentType) throws Exception {
|
||||
minioClient.putObject(PutObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(filePath)
|
||||
.stream(stream, stream.available(), -1)
|
||||
.contentType(contentType)
|
||||
.build());
|
||||
// return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
|
||||
// .method(Method.GET)
|
||||
// .bucket(bucketName)
|
||||
// .object(filePath)
|
||||
// .expiry(7, TimeUnit.DAYS)
|
||||
// .build());
|
||||
return StrUtil.format("{}/{}/{}", domain,bucketName, filePath);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.nflg.wms.starter.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nflg.wms.starter.service.FileUploadService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import software.amazon.awssdk.core.sync.RequestBody;
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
|
||||
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "file.upload.type", havingValue = "rustfs")
|
||||
public class RustFSServiceImpl implements FileUploadService {
|
||||
|
||||
@Value("${rustfs.bucket-name}")
|
||||
private String bucketName;
|
||||
|
||||
@Value("${rustfs.domain}")
|
||||
private String domain;
|
||||
|
||||
@Resource
|
||||
private S3Client s3Client;
|
||||
|
||||
@Override
|
||||
public String upload(String filePath, MultipartFile file) throws Exception {
|
||||
return upload(filePath, file.getInputStream(), file.getContentType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String upload(String filePath, InputStream stream, String contentType) throws Exception {
|
||||
ensureBucketExists();
|
||||
s3Client.putObject(
|
||||
PutObjectRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.key(filePath)
|
||||
.contentType(contentType)
|
||||
.build(),
|
||||
RequestBody.fromInputStream(stream, stream.available())
|
||||
);
|
||||
return StrUtil.format("{}/{}/{}", domain, bucketName, filePath);
|
||||
}
|
||||
|
||||
private void ensureBucketExists() {
|
||||
try {
|
||||
s3Client.headBucket(HeadBucketRequest.builder().bucket(bucketName).build());
|
||||
} catch (NoSuchBucketException e) {
|
||||
s3Client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue