Spring boot: uploading and downloading file from Minio object store

Spring boot: uploading and downloading file from Minio object store

If you have landed on this page means either your working with spring boot and trying to upload an file to a privately hosted minio object store server. so we know spring boot has gained popularity for its simple approach  to bootstrap an application in very less time, Also minio is gaining lot of popularity these days as people want to host their own data in  private cloud space. if your wondering what is minio its yet another object store making  the owner and managed by your system administrators. And by the way if you need getting started guide with minio please follow the below guide.

MINIO: Getting Started With Ubuntu 18.04
Minio is another object store just like AWS S3, This is self hosted so easilycan be used in private cloud. and it is open source so its absolute free use andmodify. this one of the fastest growing self managed object store out there. sowhen it comes to object store files are not packed into singl…

So now we shall see how to upload and download file from minio server using spring boot.

1) Dependency  

only dependency we need is minio client sdk. as developer most of us tend to copy paste without reading completely so i am pasting complete dependency of my set up.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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 http://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>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ashrithgn</groupId>
    <artifactId>miniodemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>miniodemo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>6.0.8</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.8.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.8.0</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>



        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2) Now Lets add required constants into our application.properties file.

minio.buckek.name=test
minio.default.folder=/
server.port=8000        
minio.access.name=minioadmin
minio.access.secret=minioadmin
minio.url=http://127.0.0.1:9000

no we have partially completed our set up. so just like s3 bucket is place where the files are stored in simple words its the root folder or mount point, and access and secret is the authentication required to access minio server.

3) Creating Configuration class which return the minio client.

As a Spring boot developer i have bad notion of autowiring stuff as it creates singleton object and does not create new object every time. below code is grabs config form property file and returns an instance of the minio client which we use to upload and download file using the client.

//add your package 
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration

@Configuration
public class MinioConfig {
    @Value("${minio.access.name}")
    String accessKey;
    @Value("${minio.access.secret}")
    String accessSecret;
    @Value("${minio.url}")
    String minioUrl;

    @Bean
    public MinioClient generateMinioClient() {
        try {
            MinioClient client = new MinioClient(minioUrl, accessKey, accessSecret);
            return client;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

    }


}

The Adaptor Service class which implements file upload and download logic.

As i am not a design expert so naming convection used for this could be wrong, so make sure you rename according to your design spec :-P.

//  package is mission
import io.minio.MinioClient;
import io.minio.messages.Bucket;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.List;

@Service
public class MinioAdapter {

    @Autowired
    MinioClient minioClient;

    @Value("${minio.buckek.name}")
    String defaultBucketName;

    @Value("${minio.default.folder}")
    String defaultBaseFolder;

    public List<Bucket> getAllBuckets() {
        try {
            return minioClient.listBuckets();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

    }


    public void uploadFile(String name, byte[] content) {
        File file = new File("/tmp/" + name);
        file.canWrite();
        file.canRead();
        try {
            FileOutputStream iofs = new FileOutputStream(file);
            iofs.write(content);
            minioClient.putObject(defaultBucketName, defaultBaseFolder + name, file.getAbsolutePath());
        } catch (Exception e) {
           throw new RuntimeException(e.getMessage());
        }

    }

    public byte[] getFile(String key) {
        try {
            InputStream obj = minioClient.getObject(defaultBucketName, defaultBaseFolder + "/" + key);

            byte[] content = IOUtils.toByteArray(obj);
            obj.close();
            return content;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @PostConstruct
    public void init() {
    }
}

So Now lets implement controller, basically i have written three end points which list the available buckets, and one end point to upload the file, and another end point to download the file.

import com.costrategix.s3demo.config.s3.MinioAdapter;
import io.minio.messages.Bucket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class MinioStorageController {
    @Autowired
    MinioAdapter minioAdapter;

    @GetMapping(path = "/buckets")
    public List<Bucket> listBuckets() {
        return minioAdapter.getAllBuckets();
    }

    @PostMapping(path = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public Map<String, String> uploadFile(@RequestPart(value = "file", required = false) MultipartFile files) throws IOException {
        minioAdapter.uploadFile(files.getOriginalFilename(), files.getBytes());
        Map<String, String> result = new HashMap<>();
        result.put("key", files.getOriginalFilename());
        return result;
    }

    @GetMapping(path = "/download")
    public ResponseEntity<ByteArrayResource> uploadFile(@RequestParam(value = "file") String file) throws IOException {
        byte[] data = minioAdapter.getFile(file);
        ByteArrayResource resource = new ByteArrayResource(data);

        return ResponseEntity
                .ok()
                .contentLength(data.length)
                .header("Content-type", "application/octet-stream")
                .header("Content-disposition", "attachment; filename=\"" + file + "\"")
                .body(resource);

    }
}

 So you can use Postman or any API testing tool and hit the end point and verify if the files are being uploaded as well as it could be downloaded and opened. you also refer to similar tutorials  below

AWS S3 with Spring Boot: Uploading and downloading file to Buckets
So if are reading this Article means your a developer and your familiar withspring boot or AWS S3, just for SEO purpose i will brief both,so you can skipthe introduction part and jump into coding part.As a developer Spring boot hasbecome my vital Framework and preferred choice of man developer, i…
Tutorial: Upload and download file in spring boot application RESTAPI
Spring boot is as an awesome framework where we could rapidly start our webdevelopment project with in minutes,java based configuration simplifiesbootstrapping time where we could include third party library or other componentinto our applications. and to upload file in spring boot application is…