Java上传文件到minio

前置知识:阅读这篇文章前,确保你已经会用Docker、SpringBoot、以及掌握了一些常见的开发规范。

注意:本文针对的是较小文件的上传,如图片等。如果是长视频等大文件,可能还需要用到文件分片、断点续传等,而对于这些,本文暂未提及。

1、搭建minio服务端(用Docker)

拉取镜像:

docker pull minio/minio

创建运行容器:

docker run -p 9000:9000 -p 9090:9090 \
--name minio \
-e "MINIO_ROOT_USER=账号" \
-e "MINIO_ROOT_PASSWORD=密码" \
-v /app/minio/data:/data \
-v /app/minio/config:/root/.minio \
-d minio/minio:latest \
server /data --console-address ":9090" --address ":9000"

参数及可选项说明:

注意:账号长度必须大于等于5,密码长度必须大于等于8位。

server /data:这是传递给MinIO程序的命令行参数,告诉MinIO以服务器模式运行,并且使用/data目录作为其数据存储位置。

--console-address ":9090":这个可选项指定MinIO控制台服务的端口。必须和server /data在同一行。

--address ":9000":这个可选项指定MinIO API服务的监听地址和端口。必须和server /data在同一行。

浏览器输入ip:9090,如:192.168.186.100:9090,即可访问minio服务端的控制台。

2、创建桶

可以直接在minio控制台创建桶,也可以之后在代码中创建桶。创建完不要忘记将桶的读写权限设为public。

3、项目中使用minIO

3.1、🍀引依赖

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.4.3</version>
</dependency>
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.8.1</version>
</dependency>

3.2、🍀application.yml中配置连接信息

注意:下面这段是自定义的配置,等下需要我们自己用@Value注解或者@ConfigurationProperties注解来读取yml配置。

minio:
  endpoint: http://ip地址:9000 # 注意这里一定要加“http://”,否则可能出错
  accessKey: 账号
  secretKey: 密码
  bucket: 桶名称

3.3、🍀读取yml配置

在properties包下新建MinioProperties类:

package com.daomi.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "minio")
@Data
public class MinioProperties {
    private String endpoint;

    private String accessKey;

    private String secretKey;

    private String bucket;
}

3.4、🍀配置类中声明minio的客户端对象

在config包下新建配置类MinioConfig:

package com.daomi.config;

import com.daomi.properties.MinioProperties;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {
    @Autowired
    private MinioProperties minioProperties;

    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
    }
}

3.5、🍀写工具类

添加下面的依赖:

<!--j256工具获取文件类型(mimetype)-->
<dependency>
    <groupId>com.j256.simplemagic</groupId>
    <artifactId>simplemagic</artifactId>
    <version>1.17</version>
</dependency>
<!--Apache工具包,计算文件md5值-->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.16.1</version>
</dependency>

util包下新建MinioUtil工具类(下面TODO的地方,可能是需要你根据自己项目的情况来改动的):

package com.aa.util;

import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;

@Component
@Slf4j
public class MinioUtil {

    @Autowired
    private MinioClient minioClient;

    /**
     * 上传文件到minio,并返回访问该文件的url
     * @param bucket 桶名称
     * @param multipartFile MultipartFile对象
     * @return
     */
    public String uploadFile(String bucket, MultipartFile multipartFile){
        String localFileAbsolutePath = null;
        String minioPath = null;
        try {
            // TODO 下面用this来调用的都是抽取出来的方法,我这里将它们都放在这个工具类下了。你也可以将这些方法放到其他工具类下
            // 获取文件扩展名
            String extension = this.getExtension(multipartFile);
            // 获取mimeType
            String mimeType = this.getMimeType(extension);
            // 获取本地文件的路径(源路径)
            File localFile = File.createTempFile("minio", ".temp");
            multipartFile.transferTo(localFile);
            localFileAbsolutePath = localFile.getAbsolutePath();
            // 构造minio中的路径(目标路径)=年+月+日+md5值+扩展名
            // TODO 下面的folder是上传后的文件在桶里面的路径。你也可以不指定,若不指定文件上传后就直接在桶下
            String folder = "other/" + DateUtil.generateFolderOfCurrentDate();
            // TODO 实际开发中,通常将文件的md5值作为文件名。当然你也可以用其他的作为文件名
            String fileName = DigestUtils.md5Hex(new FileInputStream(localFile));
            minioPath = folder + fileName + extension;
            // 构造UploadObjectArgs对象
            UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
                    .bucket(bucket)
                    .filename(localFileAbsolutePath)// 本地文件的路径(源路径)
                    .object(minioPath)// minio中的路径(目标路径)
                    .contentType(mimeType)
                    .build();
            // 上传文件
            minioClient.uploadObject(uploadObjectArgs);
        } catch (Exception e) {
            log.error("文件上传失败!本地源文件路径:{},minio目标文件路径:{},错误信息:{}", localFileAbsolutePath, minioPath, e.getMessage());
            e.printStackTrace();
            // TODO 这里你可以抛出你自定义的业务异常
            // throw new FileUploadFailedException(MessageConstant.FILE_UPLOAD_FAILED);
        }
        log.info("文件上传成功!本地源文件路径:{},minio目标文件路径:{}", localFileAbsolutePath, minioPath);
        // 返回访问该文件的url
        return "/" + bucket + "/" + minioPath;
    }

    /**
     * 根据MultipartFile对象获取其文件扩展名
     * @param multipartFile MultipartFile对象
     * @return
     */
    private static String getExtension(MultipartFile multipartFile) {
        String filename = multipartFile.getOriginalFilename();
        String extension = filename.substring(filename.lastIndexOf("."));
        return extension;
    }

    /**
     * 根据扩展名获取文件类型(mimetype)
     * @param extension 文件的扩展名,如:“.png”
     * @return
     */
    public static String getMimeType(String extension) {
        if (extension == null){
            extension = "";
        }
        // 根据文件扩展名获取文件类型
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension);
        if (extensionMatch != null){
            mimeType = extensionMatch.getMimeType();
        }
        return mimeType;
    }
}

3.6、⚠注意事项

实际开发中,应该在上传文件到minio前,查询数据库中是否已经存了该文件的信息,并且为了保险起见,还应额外查minio中是否也已经存在了该文件。已存在就不用重复上传。

要使用Java上传文件Minio,需要使用Minio Java客户端SDK。以下是一个示例代码,可以将本地文件上传Minio服务器。 首先,你需要在项目中添加以下依赖项: ```xml <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.1.0</version> </dependency> ``` 然后,你可以使用以下代码将文件上传Minio服务器: ```java import io.minio.MinioClient; import io.minio.errors.MinioException; import java.io.File; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; public class MinioUploader { public static void main(String[] args) { try { // Initialize the Minio client MinioClient client = new MinioClient("http://localhost:9000", "access_key", "secret_key"); // Check if the bucket exists, create it if it does not String bucketName = "my-bucket"; boolean found = client.bucketExists(bucketName); if (!found) { client.makeBucket(bucketName); } // Upload the file to the bucket String fileName = "test.txt"; File file = new File("/path/to/test.txt"); client.putObject(bucketName, fileName, file.getAbsolutePath(), null, null, null, null); System.out.println("File uploaded successfully."); } catch (IOException | NoSuchAlgorithmException | InvalidKeyException | MinioException e) { System.out.println("Error occurred: " + e.getMessage()); } } } ``` 在上面的代码中,我们首先使用MinioClient对象初始化Minio客户端,并检查我们要上传到的桶是否存在。如果桶不存在,我们使用makeBucket()方法创建它。然后,我们使用putObject()方法将文件上传到桶中。 你需要将上面的代码中的以下值替换为你自己的值: - http://localhost:9000 - Minio服务器的URL - access_key - Minio的访问密钥 - secret_key - Minio的秘密密钥 - my-bucket - 你要上传到的桶的名称 - /path/to/test.txt - 你要上传的本地文件的路径。 注意:如果你的文件是大文件,你应该使用putObject()方法的其他重载版本,以支持分片上传
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值