没有安装MinIO的,可以点击安装,安装过的直接跳过。
完整配置文件:
<?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 https://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.7.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.test</groupId>
<artifactId>springboot-minio</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-minio</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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- hutool 工具包,各种封装功能 一应俱全-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
<!-- minio 相关依赖 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.0.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml:
# minio 文件存储配置信息
minio:
#url
endpoint: http://127.0.0.1:9000
#账号
accessKey: minioadmin
#密码
secretKey: minioadmin
#桶
bucketName: testbucket
MinIoClientConfig:
package com.test.config;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Data
@Component
public class MinIoClientConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Value("${minio.bucketName}")
private String bucketName;
/**
* 注入minio 客户端
* @return
*/
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
MinioUtils :
package com.test.utils;
import com.test.config.MinIoClientConfig;
import io.minio.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @description: minio工具类
* @version:3.0
*/
@Component
public class MinioUtils {
@Autowired
private MinioClient minioClient;
@Autowired
private MinIoClientConfig minIoClientConfig;
/**
* description: 判断bucket是否存在,不存在则创建
*
* @return: void
*/
public void existBucket(String name) {
try {
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建存储bucket
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean makeBucket(String bucketName) {
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 删除存储bucket
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* description: 上传文件
*
* @param file
* @return: java.lang.String
*/
public String upload(MultipartFile file) {
String fileName = file.getOriginalFilename();
String[] split = fileName.split("\\.");
if (split.length > 1) {
fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
} else {
fileName = fileName + System.currentTimeMillis();
}
InputStream in = null;
try {
in = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(minIoClientConfig.getBucketName())
.object(fileName)
.stream(in, in.available(), -1)
.contentType(file.getContentType())
.build()
);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
String filePath = minIoClientConfig.getEndpoint() + File.separator + minIoClientConfig.getBucketName() + File.separator + fileName;
return filePath;
}
/**
* description: 上传文件
*
* @param multipartFile
* @return: java.lang.String
*/
public List<String> uploads(MultipartFile[] multipartFile) {
List<String> names = new ArrayList<>(multipartFile.length);
for (MultipartFile file : multipartFile) {
String fileName = file.getOriginalFilename();
String[] split = fileName.split("\\.");
if (split.length > 1) {
fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
} else {
fileName = fileName + System.currentTimeMillis();
}
InputStream in = null;
try {
in = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(minIoClientConfig.getBucketName())
.object(fileName)
.stream(in, in.available(), -1)
.contentType(file.getContentType())
.build()
);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
names.add(fileName);
}
return names;
}
/**
* description: 下载文件
*
* @param fileName
* @return: org.springframework.http.ResponseEntity<byte [ ]>
*/
public ResponseEntity<byte[]> download(String fileName) {
ResponseEntity<byte[]> responseEntity = null;
InputStream in = null;
ByteArrayOutputStream out = null;
try {
in = minioClient.getObject(GetObjectArgs.builder().bucket(minIoClientConfig.getBucketName()).object(fileName).build());
out = new ByteArrayOutputStream();
IOUtils.copy(in, out);
//封装返回值
byte[] bytes = out.toByteArray();
HttpHeaders headers = new HttpHeaders();
try {
headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
headers.setContentLength(bytes.length);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setAccessControlExposeHeaders(Arrays.asList("*"));
responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return responseEntity;
}
/**
* 查看文件对象
* @param bucketName 存储bucket名称
* @return 存储bucket内文件对象信息
*/
public List<ObjectItem> listObjects(String bucketName) {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucketName).build());
List<ObjectItem> objectItems = new ArrayList<>();
try {
for (Result<Item> result : results) {
Item item = result.get();
ObjectItem objectItem = new ObjectItem();
objectItem.setObjectName(item.objectName());
objectItem.setSize(item.size());
objectItems.add(objectItem);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return objectItems;
}
/**
* 批量删除文件对象
* @param bucketName 存储bucket名称
* @param objects 对象名称集合
*/
public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
return results;
}
}
ObjectItem :
package com.test.utils;
import lombok.Data;
@Data
public class ObjectItem {
private String objectName;
private Long size;
}
package com.test.controller;
import com.test.utils.MinioUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/test")
@AllArgsConstructor
@Slf4j
public class MinioController {
private final MinioUtils minioUtils;
@PostMapping("/upload")
public String upload(MultipartFile file) {
return minioUtils.upload(file);
}
@RequestMapping("/download")
public Object download(String fileName) {
ResponseEntity<byte[]> responseEntity = minioUtils.download(fileName);
return responseEntity;
}
}
访问上传接口:
可以看到,文件已经上传成功了。
浏览器访问下载接口:
http://localhost:8080/test/download?fileName=微信图片_20230331150206_1680252652331.jpg
也可以在浏览器直接访问文件的路径:
http://ip:9000/testbucket/微信图片_20230331150206_1680252652331.jpg
注意: MinIO创建的桶,默认访问策略是private,要将他设置为public,否则文件下载不了!
解决方案:
选择public就可以了。