Appearance
前置知识 技术栈-MinIO使用教程
文件上传流程
下面是一张标准的使用 MinIO 作为存储的文件上传流程示意图。

整合 MinIO 实现文件上传
整合依赖及配置
- 在
pom.xml中添加 MinIO Java SDK 的相关依赖:
xml
<!--MinIO Java SDK依赖-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>- 修改
application.yml配置文件,在 SpringBoot 中开启文件上传功能,并添加 MinIO 客户端配置。
yaml
spring:
servlet:
multipart:
enabled: true #开启文件上传
max-file-size: 10MB #限制文件上传大小为10M
minio:
endpoint: http://localhost:9000 #MinIO服务所在地址
bucketName: mall #存储桶名称
accessKey: minioadmin #访问的key
secretKey: minioadmin #访问的秘钥实现文件上传功能
- 添加一个
MinioController控制器用于实现文件的上传和删除操作:
java
/**
* @auther macrozheng
* @description MinIO对象存储管理Controller
* @date 2019/12/25
* @github [macrozheng - Overview](https://github.com/macrozheng)
*/
@Controller
@Api(tags = "MinioController")
@Tag(name = "MinioController", description = "MinIO对象存储管理")
@RequestMapping("/minio")
public class MinioController {
private static final Logger LOGGER = LoggerFactory.getLogger(MinioController.class);
@Value("${minio.endpoint}")
private String ENDPOINT;
@Value("${minio.bucketName}")
private String BUCKET_NAME;
@Value("${minio.accessKey}")
private String ACCESS_KEY;
@Value("${minio.secretKey}")
private String SECRET_KEY;
@ApiOperation("文件上传")
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public CommonResult upload(@RequestPart("file") MultipartFile file) {
try {
//创建一个MinIO的Java客户端
MinioClient minioClient = MinioClient.builder()
.endpoint(ENDPOINT)
.credentials(ACCESS_KEY, SECRET_KEY)
.build();
boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(BUCKET_NAME).build());
if (isExist) {
LOGGER.info("存储桶已经存在!");
} else {
//创建存储桶并设置只读权限
minioClient.makeBucket(MakeBucketArgs.builder().bucket(BUCKET_NAME).build());
BucketPolicyConfigDto bucketPolicyConfigDto = createBucketPolicyConfigDto(BUCKET_NAME);
SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder()
.bucket(BUCKET_NAME)
.config(JSONUtil.toJsonStr(bucketPolicyConfigDto))
.build();
minioClient.setBucketPolicy(setBucketPolicyArgs);
}
String filename = file.getOriginalFilename();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 设置存储对象名称
String objectName = sdf.format(new Date()) + "/" + filename;
// 使用putObject上传一个文件到存储桶中
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(BUCKET_NAME)
.object(objectName)
.contentType(file.getContentType())
.stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE).build();
minioClient.putObject(putObjectArgs);
LOGGER.info("文件上传成功!");
MinioUploadDto minioUploadDto = new MinioUploadDto();
minioUploadDto.setName(filename);
minioUploadDto.setUrl(ENDPOINT + "/" + BUCKET_NAME + "/" + objectName);
return CommonResult.success(minioUploadDto);
} catch (Exception e) {
e.printStackTrace();
LOGGER.info("上传发生错误: {}!", e.getMessage());
}
return CommonResult.failed();
}
/**
* 创建存储桶的访问策略,设置为只读权限
*/
private BucketPolicyConfigDto createBucketPolicyConfigDto(String bucketName) {
BucketPolicyConfigDto.Statement statement = BucketPolicyConfigDto.Statement.builder()
.Effect("Allow")
.Principal("*")
.Action("s3:GetObject")
.Resource("arn:aws:s3:::" + bucketName + "/*.**").build();
return BucketPolicyConfigDto.builder()
.Version("2012-10-17")
.Statement(CollUtil.toList(statement))
.build();
}
@ApiOperation("文件删除")
@RequestMapping(value = "/delete", method = RequestMethod.POST)
@ResponseBody
public CommonResult delete(@RequestParam("objectName") String objectName) {
try {
MinioClient minioClient = MinioClient.builder()
.endpoint(ENDPOINT)
.credentials(ACCESS_KEY, SECRET_KEY)
.build();
minioClient.removeObject(RemoveObjectArgs.builder().bucket(BUCKET_NAME).object(objectName).build());
return CommonResult.success(null);
} catch (Exception e) {
e.printStackTrace();
}
return CommonResult.failed();
}
}- 其中的
BucketPolicyConfigDto类是存储桶访问策略的封装类,这里在创建存储桶时,对应匿名用户设置了只读权限:
java
/**
* @auther macrozheng
* @description Minio Bucket访问策略配置
* @date 2020/8/11
* @github [macrozheng - Overview](https://github.com/macrozheng)
*/
@Data
@EqualsAndHashCode
@Builder
public class BucketPolicyConfigDto {
private String Version;
private List<Statement> Statement;
@Data
@EqualsAndHashCode
@Builder
public static class Statement {
private String Effect;
private String Principal;
private String Action;
private String Resource;
}
}- 其中的
MinioUploadDto类封装了文件上传的返回结果:
java
/**
* @auther macrozheng
* @description 文件上传返回结果
* @date 2019/12/25
* @github [macrozheng - Overview](https://github.com/macrozheng)
*/
@Data
@EqualsAndHashCode
public class MinioUploadDto {
@ApiModelProperty("文件访问URL")
private String url;
@ApiModelProperty("文件名称")
private String name;
}- 如果我们在前后端分类项目中使用 SpringBoot 提供的 API 接口,还需要添加一个全局的跨域请求配置。
java
/**
* @auther macrozheng
* @description 全局跨域配置
* @date 2019/7/27
* @github [macrozheng - Overview](https://github.com/macrozheng)
*/
@Configuration
public class GlobalCorsConfig {
/**
* 允许跨域调用的过滤器
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOriginPattern("*");
//允许跨越发送cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}文件上传功能演示
- 运行项目,访问 Swagger API 文档,访问地址:http://localhost:8080/swagger-ui/
- 通过
/minio/upload接口进行文件上传操作; - 上传完成后,我们打开 MinIO 的管理界面可以看到上传后的图片,也可以通过返回的 url 来访问图片:

- 通过
/minio/delete接口我们可以删除存储的图片,需要注意的是objectName值是存储桶中的图片相对路径。
