Dependencies and Configuration
Add MinIO SDK dependency in pom.xml:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.7</version>
</dependency>
Configure application.yml:
minio:
endpoint: http://server-ip:9000
access-id: minio-user
secret-key: secure-pass
container: ruoyi-files
Client Configuration
@Configuration
public class ObjectStorageConfig {
@Value("${minio.access-id}")
private String accessId;
@Value("${minio.secret-key}")
private String secretKey;
@Value("${minio.endpoint}")
private String endpoint;
@Bean
public MinioClient storageClient() {
return MinioClient.builder()
.credentials(accessId, secretKey)
.endpoint(endpoint)
.build();
}
}
Storage Service Implementation
@Service
public class ObjectStorageService {
@Autowired
private MinioClient client;
@Value("${minio.container}")
private String containerName;
public String saveObject(MultipartFile file) throws Exception {
String objectName = generateFilename(file.getOriginalFilename());
try (InputStream stream = file.getInputStream()) {
createContainerIfMissing();
client.putObject(PutObjectArgs.builder()
.bucket(containerName)
.object(objectName)
.stream(stream, file.getSize(), -1)
.contentType(file.getContentType())
.build());
return "/" + containerName + "/" + objectName;
}
}
private void createContainerIfMissing() throws Exception {
if (!client.bucketExists(BucketExistsArgs.builder().bucket(containerName).build())) {
client.makeBucket(MakeBucketArgs.builder().bucket(containerName).build());
client.setBucketPolicy(SetBucketPolicyArgs.builder()
.bucket(containerName)
.config(getContainerPolicy())
.build());
}
}
private String getContainerPolicy() {
return String.format("{\"Version\":\"2012-10-17\",\"Statement\":["
+ "{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":"
+ "[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":"
+ "[\"arn:aws:s3:::%s\"]}]}", containerName);
}
}
API Controller
@RestController
@RequestMapping("/storage")
public class StorageController {
@Autowired
private ObjectStorageService storageService;
@PostMapping("/upload")
public ResponseEntity<Map<String, String>> upload(@RequestParam("file") MultipartFile file) {
try {
String path = storageService.saveObject(file);
return ResponseEntity.ok(Map.of(
"path", path,
"originalName", file.getOriginalFilename()
));
} catch (Exception ex) {
return ResponseEntity.status(500).body(Map.of("error", ex.getMessage()));
}
}
}
MinIO Server Deployment
Run MinIO server using Docker:
docker run -d --name minio-server \
-p 9000:9000 -p 9001:9001 \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=admin123" \
-v /mnt/minio-data:/data \
minio/minio server /data --console-address ":9001"
Container Configuration
- Acess console at http://server-ip:9001
- Create new container matching application.yml configuration
- Set containerr acces policy to public
- Create dedicated user with read-write permissions
Verification and Troubleshooting
- Test file upload via API client
- Verify object appears in MinIO console
- Check network connectivity between application server and MinIO
- Validate container permissions and user credentials
- Ensure firewall allows traffic on ports 9000/9001