Implementing Image Uploads with MinIO Object Storage in Spring Boot

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.

Tags: Spring Boot MinIO Object Storage File Upload docker

Posted on Sat, 12 Sep 2026 16:54:36 +0000 by ccrevcypsys