SpringBoot 集成 RustFS
- 1 配置
- 2 依赖
- 3 代码
- 3.1 FileController
- 3.2 RustFsConfig
- 3.3 RustFsProperties
- 3.4 RustFsStorageService
1 配置
1.1 Docker容器
services:rustfs:image:rustfs/rustfs:latestcontainer_name:rustfsrestart:unless-stoppedsecurity_opt:-"no-new-privileges:true"networks:-hyacinthports:-"9500:9000"# S3 API,避开 MinIO 的 9000-"9501:9001"# RustFS 控制台environment:# 本机单磁盘开发模式,避免把同一物理磁盘伪装成四块独立磁盘。RUSTFS_VOLUMES:/dataRUSTFS_ADDRESS:0.0.0.0:9000RUSTFS_CONSOLE_ADDRESS:0.0.0.0:9001RUSTFS_CONSOLE_ENABLE:"true"RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS:"*"RUSTFS_ACCESS_KEY:rustfsadminRUSTFS_SECRET_KEY:rustfsadminRUSTFS_OBS_LOGGER_LEVEL:infoRUSTFS_OBS_LOG_DIRECTORY:/app/logsvolumes:-D:/Env/docker/rustfs/data:/data-D:/Env/docker/rustfs/logs:/app/logs
![]()
1.2 Spring配置
spring:application:name:spring-fileservlet:multipart:max-file-size:100MBmax-request-size:100MBrustfs:endpoint:${RUSTFS_ENDPOINT:http://localhost:9500}access-key:${RUSTFS_ACCESS_KEY:rustfsadmin}secret-key:${RUSTFS_SECRET_KEY:rustfsadmin}region:${RUSTFS_REGION:us-east-1}bucket:${RUSTFS_BUCKET:spring-file}
2 依赖
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>4.1.1</version><relativePath/></parent><groupId>com.xu</groupId><artifactId>spring-file</artifactId><version>1.0.0</version><properties><java.version>25</java.version></properties><dependencyManagement><dependencies><dependency><groupId>software.amazon.awssdk</groupId><artifactId>bom</artifactId><version>2.55.6</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>software.amazon.awssdk</groupId><artifactId>s3</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webmvc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webmvc-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><executions><execution><id>default-compile</id><phase>compile</phase><goals><goal>compile</goal></goals><configuration><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path></annotationProcessorPaths></configuration></execution><execution><id>default-testCompile</id><phase>test-compile</phase><goals><goal>testCompile</goal></goals><configuration><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path></annotationProcessorPaths></configuration></execution></executions></plugin></plugins></build></project>
3 代码
3.1 FileController
packagecom.xu.spring.file.rustfs;importjava.io.IOException;importjava.util.Map;importorg.springframework.http.MediaType;importorg.springframework.web.bind.annotation.DeleteMapping;importorg.springframework.web.bind.annotation.PathVariable;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.multipart.MultipartFile;@RestController@RequestMapping("/api/files")publicclassFileController{privatefinalRustFsStorageServicestorageService;publicFileController(RustFsStorageServicestorageService){this.storageService=storageService;}@PostMapping(consumes={MediaType.MULTIPART_FORM_DATA_VALUE,MediaType.MULTIPART_MIXED_VALUE})publicMap<String,String>upload(@RequestParam("file")MultipartFilefile)throwsIOException{StringobjectKey=storageService.upload(file);returnMap.of("message","上传成功","key",objectKey);}@DeleteMapping("/{key}")publicMap<String,String>delete(@PathVariableStringkey){storageService.delete(key);returnMap.of("message","删除成功");}}
3.2 RustFsConfig
packagecom.xu.spring.file.rustfs;importjava.net.URI;importorg.springframework.boot.context.properties.EnableConfigurationProperties;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importsoftware.amazon.awssdk.auth.credentials.AwsBasicCredentials;importsoftware.amazon.awssdk.auth.credentials.StaticCredentialsProvider;importsoftware.amazon.awssdk.regions.Region;importsoftware.amazon.awssdk.services.s3.S3Client;@Configuration@EnableConfigurationProperties(RustFsProperties.class)publicclassRustFsConfig{@BeanpublicS3ClientrustFsS3Client(RustFsPropertiesproperties){AwsBasicCredentialscredentials=AwsBasicCredentials.create(properties.accessKey(),properties.secretKey());returnS3Client.builder().endpointOverride(URI.create(properties.endpoint())).region(Region.of(properties.region())).credentialsProvider(StaticCredentialsProvider.create(credentials)).forcePathStyle(true).build();}}
3.3 RustFsProperties
packagecom.xu.spring.file.rustfs;importorg.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix="rustfs")publicrecordRustFsProperties(Stringendpoint,StringaccessKey,StringsecretKey,Stringregion,Stringbucket){}
3.4 RustFsStorageService
packagecom.xu.spring.file.rustfs;importjava.io.IOException;importjava.io.InputStream;importjava.util.UUID;importorg.springframework.stereotype.Service;importorg.springframework.util.StringUtils;importorg.springframework.web.multipart.MultipartFile;importsoftware.amazon.awssdk.core.sync.RequestBody;importsoftware.amazon.awssdk.services.s3.S3Client;importsoftware.amazon.awssdk.services.s3.model.DeleteObjectRequest;importsoftware.amazon.awssdk.services.s3.model.PutObjectRequest;@ServicepublicclassRustFsStorageService{privatefinalS3Clients3Client;privatefinalRustFsPropertiesproperties;publicRustFsStorageService(S3Clients3Client,RustFsPropertiesproperties){this.s3Client=s3Client;this.properties=properties;}publicStringupload(MultipartFilefile)throwsIOException{if(file.isEmpty()){thrownewIllegalArgumentException("上传文件不能为空");}Stringsuffix="";StringoriginalFilename=file.getOriginalFilename();if(StringUtils.hasText(originalFilename)){intindex=originalFilename.lastIndexOf('.');if(index>=0){suffix=originalFilename.substring(index);}}StringobjectKey=UUID.randomUUID()+suffix;PutObjectRequestrequest=PutObjectRequest.builder().bucket(properties.bucket()).key(objectKey).contentType(StringUtils.hasText(file.getContentType())?file.getContentType():"application/octet-stream").build();try(InputStreaminputStream=file.getInputStream()){s3Client.putObject(request,RequestBody.fromInputStream(inputStream,file.getSize()));}returnobjectKey;}publicvoiddelete(StringobjectKey){DeleteObjectRequestrequest=DeleteObjectRequest.builder().bucket(properties.bucket()).key(objectKey).build();s3Client.deleteObject(request);}}