Minio file upload

In today’s digital age, data storage has become a crucial task. As your business grows and data increases, it becomes increasingly important to choose a storage solution that is efficient, reliable, and easy to manage. Minio is an open source cloud storage tool with powerful functions and scalability, providing enterprises with reliable storage solutions.

1. Features of Minio

Minio is a high-performance, scalable object storage server with the following features:

  1. Scalability: Minio can easily scale to hundreds of nodes and tens of petabytes of storage capacity.
  2. Cloud native: Minio can easily integrate with cloud service providers such as AWS, Azure, and Google Cloud.
  3. Highly reliable: Minio adopts a distributed architecture, providing high availability and data redundancy.
  4. Flexibility: Minio supports multiple storage classes, including S3 compatible, file storage and block storage.
  5. Open Source: Minio is open source, free to use and customized according to your needs.

2. Minio tool class sample code

  1. First, you need to add the dependency of MinIO Java SDK in your project’s pom.xml file.
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>4.4.0</version>
</dependency>
  1. Next, you need to create a MinIO client configuration object and specify the MinIO server’s URL, access key, and secret key. You can store these values in environment variables or configuration files.

minio.properties

minio.url=http://127.0.0.1:9000 #MinIO service address
minio.accessKey=admin #Access key
minio.secretKey=admin123 #Access secret key
minio.bucketName=test #Bucket name
  1. Read configuration class
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.minio.MinioClient;

@Configuration
public class MinioConfig {<!-- -->

/**
* Service address
*/
@Value("${minio.url}")
private String url;

/**
\t * username
*/
@Value("${minio.accessKey}")
private String accessKey;

/**
\t * password
*/
@Value("${minio.secretKey}")
private String secretKey;


@Bean
public MinioClient getMinioClient() {<!-- -->
return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
}

}

  1. The following is a simple Minio tool class sample code for connecting to the Minio server and operating buckets and objects:

import io.minio.*;
import io.minio.http.Method;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class MinioClientUtil {<!-- -->

    private static final Logger log = Logger.getLogger(MinioClientUtil.class);


    @Autowired
    private MinioClient minioClient;

    /**
     * Service address
     */
    @Value("${minio.url}")
    private String url;
    /**
     * Bucket name
     */
    @Value("${minio.bucketName}")
    private String bucketName;


    public MinioClient getMinioClient() {<!-- -->
        return minioClient;
    }
    //Operation bucket

    /**
     * Create bucket
     *
     * @param bucketName
     */
    public void makeBucket(String bucketName) {<!-- -->
        try {<!-- -->
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {<!-- -->
            System.out.println("Error occurred while creating bucket: " + e);
        }
    }

    // Delete bucket
    public boolean removeBucket(String bucketName) {<!-- -->
        try {<!-- -->
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
            return true;
        } catch (Exception e) {<!-- -->
            System.out.println("Error occurred while removing bucket: " + e);
            return false;
        }
    }

    // Check if the bucket exists
    public boolean bucketExists(String bucketName) {<!-- -->
        try {<!-- -->
            return minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {<!-- -->
            System.out.println("Error occurred while checking bucket existence: " + e);
            return false;
        }
    }

    //Upload the object to the bucket
    public void putObject(String bucketName, String objectName, InputStream data, long dataSize) throws IOException {<!-- -->
        try {<!-- -->
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(data, dataSize, -1) //Set the data size and segment size of the input stream. -1 means no segmentation.
                    .build());
        } catch (Exception e) {<!-- -->
            System.out.println("Error occurred while uploading object: " + e);
        } finally {<!-- -->
            if (data != null) {<!-- -->
                data.close(); // Close the input stream.
            }
        }
    }


    //Manipulate file objects

    /**
     * upload files
     * @param file
     * @param filePath
     * @return
     */
    public boolean uploadFile(MultipartFile file, String filePath) {<!-- -->
        boolean b = false;
        try {<!-- -->
            PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(filePath)
                    .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
            minioClient.putObject(args);
            b = true;
        } catch (Exception e) {<!-- -->
            b = false;
            log.error("Failed to upload file to minio!!" + e.getMessage());
        }
        return b;
    }


    public String uploadFileByUrl(MultipartFile file, String filePath) {<!-- -->
        try {<!-- -->
            PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(filePath)
                    .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
            minioClient.putObject(args);
        } catch (Exception e) {<!-- -->
            throw new RuntimeException("Failed to upload file to minio!!" + e.getMessage());
        }
        return url + "/" + bucketName + "/" + filePath;
    }

    /**
     * download attachment
     *
     * @param attachmentName original name of attachment
     * @param attachmentNameInServer The name of the attachment stored in the file server
     * @param httpServletResponse httpServletResponse
     */

    public void download(String attachmentName, String attachmentNameInServer,
                         HttpServletResponse httpServletResponse) {<!-- -->
        try {<!-- -->
            StatObjectResponse statObjectResponse = minioClient
                    .statObject(StatObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
            httpServletResponse.setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(attachmentName, "UTF-8"));
            httpServletResponse.setContentType(statObjectResponse.contentType());
            // httpServletResponse.setContentType("application/octet-stream");
            httpServletResponse.setCharacterEncoding("UTF-8");
            InputStream inputStream = minioClient
                    .getObject(GetObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
            IOUtils.copy(inputStream, httpServletResponse.getOutputStream());
        } catch (Exception e) {<!-- -->
            throw new RuntimeException("minio failed to download file!!" + e.getMessage());
        }

    }

    /**
     * Get the preview URL Note: The .txt attachment will be garbled, but the PDF will be normal Note: The default validity period is 7 days
     *
     * @param bucketName bucket name
     * @param attachmentNameInServer The name of the attachment stored in the file server
     * @return
     */

    public String getPresignedUrl(String bucketName, String attachmentNameInServer) {<!-- -->
        try {<!-- -->
            minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET)
                    .bucket(bucketName).object(attachmentNameInServer).build());
        } catch (Exception e) {<!-- -->
            throw new RuntimeException("minio failed to generate temporary file sharing link!!" + e.getMessage());
        }

    }

    /**
     * Delete attachment
     *
     * @param bucketName bucket name
     * @param attachmentNameInServer The name of the attachment stored in the file server
     */
    public void remove(String bucketName, String attachmentNameInServer) {<!-- -->
        try {<!-- -->
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
        } catch (Exception e) {<!-- -->
            throw new RuntimeException("minio failed to delete file!!" + e.getMessage());
        }
    }


    public InputStream getFileInputStream(String attachmentNameInServer) {<!-- -->
        InputStream inputStream = null;
        try {<!-- -->
            inputStream = minioClient
                    .getObject(GetObjectArgs.builder().bucket(bucketName).object(attachmentNameInServer).build());
        } catch (Exception e) {<!-- -->
            throw new RuntimeException("minio failed to download file!!" + e.getMessage());
        }
        return inputStream;
    }

    /**
     *Multiple picture zip downloads
     */
    public void batchDownload(List<String> filenames, String zip, HttpServletResponse res, HttpServletRequest
            req) {<!-- -->
        try {<!-- -->
            BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
            boolean bucketExists = minioClient.bucketExists(bucketArgs);
            BufferedOutputStream bos = null;
            res.reset();
            bos = new BufferedOutputStream(res.getOutputStream());
            ZipOutputStream out = new ZipOutputStream(bos);
            res.setHeader("Access-Control-Allow-Origin", "*");
            for (int i = 0; i < filenames.size(); i + + ) {<!-- -->
                GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName)
                        .object(filenames.get(i)).build();
                InputStream object = minioClient.getObject(objectArgs);
                byte buf[] = new byte[1024];
                int length = 0;
                res.setCharacterEncoding("utf-8");
                res.setContentType("application/force-download");//Set forced download not to open
                res.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
                res.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoding(zip, req) + ".zip");
                out.putNextEntry(new ZipEntry(filenames.get(i).substring(filenames.get(i).lastIndexOf("/") + 1)));
                while ((length = object.read(buf)) > 0) {<!-- -->
                    out.write(buf, 0, length);
                }
            }
            out.close();
            bos.close();
        } catch (Exception e) {<!-- -->
            e.printStackTrace();
        }
    }

    public static String filenameEncoding(String filename, HttpServletRequest request) throws
            UnsupportedEncodingException {<!-- -->
        // Get the User-Agent in the request header
        String agent = request.getHeader("User-Agent");
        //Encode differently according to different clients

        if (agent.contains("MSIE")) {<!-- -->
            //IE browser
            filename = URLEncoder.encode(filename, "utf-8");
        } else if (agent.contains("Firefox")) {<!-- -->
            // Firefox browser
            BASE64Encoder base64Encoder = new BASE64Encoder();
            filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
        } else {<!-- -->
            // other browsers
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
}

3. Summary

MinIO is a high-performance, scalable, and easy-to-use open source object storage service. It is compatible with the Amazon S3 cloud storage service interface and can be easily integrated with existing tools and ecosystems. MinIO is known for its excellent performance, scalability and ease of use, and is suitable for data storage needs in various scenarios. Whether in a stand-alone environment or a distributed environment, MinIO can provide reliable and efficient data storage solutions.