Setting Up MinIO Server
MinIO is an open-source object storage server that enables users to deploy private cloud storage solutions with simplicity, high availability, and scalability.
Pull Docker Image
docker pull minio/minio
Start Container
docker run -p 9000:9000 -p 9090:9090 \
--name minio-container \
-d --restart=always \
-e "MINIO_ROOT_USER=storageadmin" \
-e "MINIO_ROOT_PASSWORD=storagepassword" \
-v /opt/minio/data:/data \
minio/minio server \
/data --console-address ":9090" -address ":9000"
Verify Deployment
docker ps -a
Ensure firewall rules allow access to ports 9000 and 9090.
Access Web Console
Navigate to http://your-server-ip:9090 and login using the credentials specified during container startup.
Create Storage Bucket
Use the web interface to create a new bucket for storing objects.
Configuring Permanent Access
By default, MinIO generates temporary URLs. Install the MinIO client to configure permanent access policies.
docker pull minio/mc
docker run -it --entrypoint=/bin/sh minio/mc
mc alias set myminio http://your-ip:9000 storageadmin storagepassword
mc ls myminio
mc anonymous set download myminio/your-bucket-name
Spring Boot Implementation
Application Configuration
server:
port: 8080
minio:
endpoint: http://your-server-ip:9000
accessKey: storageadmin
secretKey: storagepassword
Storage Utility Class
@Component
public class ObjectStorageService {
@Autowired
private MinioClient storageClient;
public void ensureBucketExists(String bucketName) throws Exception {
boolean exists = storageClient.bucketExists(
BucketExistsArgs.builder().bucket(bucketName).build()
);
if (!exists) {
storageClient.makeBucket(
MakeBucketArgs.builder().bucket(bucketName).build()
);
}
}
public String storeFile(MultipartFile file, String bucketName,
String directoryPath) throws Exception {
ensureBucketExists(bucketName);
String objectIdentifier = directoryPath != null ?
directoryPath + "/" + file.getOriginalFilename() :
file.getOriginalFilename();
storageClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectIdentifier)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build()
);
return objectIdentifier;
}
public InputStream retrieveFile(String bucketName, String objectId)
throws Exception {
return storageClient.getObject(
GetObjectArgs.builder()
.bucket(bucketName)
.object(objectId)
.build()
);
}
}
REST Controller
@RestController
@RequestMapping("/api/storage")
public class FileUploadController {
@Autowired
private ObjectStorageService storageService;
@Value("${minio.endpoint}")
private String storageEndpoint;
@PostMapping("/upload")
public ResponseEntity<string> handleFileUpload(
@RequestParam("file") MultipartFile file,
@RequestParam("bucket") String bucketName,
@RequestParam(value = "path", required = false) String directoryPath) {
try {
String objectId = storageService.storeFile(file, bucketName, directoryPath);
String fileUrl = storageEndpoint + "/" + bucketName + "/" + objectId;
return ResponseEntity.ok(fileUrl);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Upload failed: " + e.getMessage());
}
}
}
</string>
Additional Features
The utility class can be extended to support file listing, deletion, and generating pre-signed URLs for temporary access.