MinIO是一个基于ApacheLicensev2.0开源协议的对象存储服务,它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,下面这篇文章主要给大家介绍了关于SpringBoot整合Minio实现上传文件的完整步骤,需要的朋友可以参考下
Minio
上传文件如果不使用云服务的话,需要本地搭建,一般选择 FastDFS 但是 FastDFS 安装比较复杂,今天了解一款安装使用更简单的存储系统 MinIO
MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。
MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。
MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。
在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品
安装 Minio
使用docker安装
拉取镜像
docker pull minio/minio
启动
docker run -p 9000:9000 -p 9001:9001 -d --name minio -v /opt/docker/minio/data:/data -v /opt/docker/minio/config:/root/.minio -e "MINIO_ROOT_USER=minio" -e "MINIO_ROOT_PASSWORD=minio@123456" minio/minio server /data --console-address ":9000" --address ":9001"
使用9000端口 登录控制台
创建存储桶
设置桶权限
创建 Java 客户端
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- minio依赖 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.1</version>
</dependency>
<!-- hutool工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.2</version>
</dependency>
<!-- 压缩图片 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<!-- 工具类依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.github.davidcarboni</groupId>
<artifactId>encrypted-</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
配置文件
spring:
application:
name: minio-demo
servlet:
multipart:
max-file-size: 20MB
max-request-size: 200MB
server:
port: 8088
minio:
endpoint: http://你的ip:9001
accessKey: minio
secretKey: minio@123456
nginxHost: http://你的域名
配置文件配置类
package com.sqm.minio_demo.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "minio")
@Component
@Data
public class MinioProperties {
/**
* 连接地址
*/
private String endpoint;
/**
* 用户名
*/
private String accessKey;
/**
* 密码
*/
private String secretKey;
/**
* 域名
*/
private String nginxHost;
}
创建 minio 客户端
package com.sqm.minio_demo.config;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {
@Autowired
private MinioProperties minioProperties;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(minioProperties.getEndpoint())
.credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey())
.build();
}
}
文件地址返回路径实体类
package com.sqm.minio_demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UploadResponse {
private String minIoUrl;
private String nginxUrl;
}
上传文件工具类
package com.sqm.minio_demo.util;
import cn.hutool.core.date.DateUtil;
import com.sqm.minio_demo.config.MinioProperties;
import com.sqm.minio_demo.entity.UploadResponse;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Optional;
import java.util.Random;
@Component
@Slf4j
public class MinioUtil {
@Autowired
private MinioProperties minioProperties;
@Autowired
private MinioClient minioClient;
private final Long maxSize = (long) (1024 * 1024);
/**
* 创建bucket
*/
public void createBucket(String bucketName) throws Exception {
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
}
/**
* 上传文件
*/
public UploadResponse uploadFile(MultipartFile file, String bucketName) throws Exception {
//判断文件是否为空
if (null == file || 0 == file.getSize()) {
return null;
}
//判断存储桶是否存在 不存在则创建
createBucket(bucketName);
//文件名
String originalFilename = file.getOriginalFilename();
//新的文件名 = 时间戳_随机数.后缀名
assert originalFilename != null;
long now = System.currentTimeMillis() / 1000;
String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +
originalFilename.substring(originalFilename.lastIndexOf("."));
//开始上传
log.info("file压缩前大小:{}",file.getSize());
if (file.getSize() > maxSize) {
FileItemFactory fileItemFactory = new DiskFileItemFactory();
FileItem fileItem = fileItemFactory.createItem(fileName, "text/plain", true, fileName);
OutputStream outputStream = fileItem.getOutputStream();
Thumbnails.of(file.getInputStream()).scale(1f).outputFormat(originalFilename.substring(originalFilename.lastIndexOf(".")+1)).outputQuality(0.25f).toOutputStream(outputStream);
file = new CommonsMultipartFile(fileItem);
}
log.info("file压缩后大小:{}",file.getSize());
minioClient.putObject(
PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;
String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;
return new UploadResponse(url, urlHost);
}
/**
* 获取全部bucket
*
* @return
*/
public List<Bucket> getAllBuckets() throws Exception {
return minioClient.listBuckets();
}
/**
* 根据bucketName获取信息
*
* @param bucketName bucket名称
*/
public Optional<Bucket> getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException, ServerException {
return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
}
/**
* 根据bucketName删除信息
*
* @param bucketName bucket名称
*/
public void removeBucket(String bucketName) throws Exception {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
}
/**
* 获取⽂件外链
*
* @param bucketName bucket名称
* @param objectName ⽂件名称
* @param expires 过期时间 <=7
* @return url
*/
public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());
}
/**
* 获取⽂件
*
* @param bucketName bucket名称
* @param objectName ⽂件名称
* @return ⼆进制流
*/
public InputStream getObject(String bucketName, String objectName) throws Exception {
return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/**
* 上传⽂件
*
* @param bucketName bucket名称
* @param objectName ⽂件名称
* @param stream ⽂件流
* @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws
Exception {
minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).contentType(objectName.substring(objectName.lastIndexOf("."))).build());
}
/**
* 上传⽂件
*
* @param bucketName bucket名称
* @param objectName ⽂件名称
* @param stream ⽂件流
* @param size ⼤⼩
* @param contextType 类型
* @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream, long
size, String contextType) throws Exception {
minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, -1).contentType(contextType).build());
}
/**
* 获取⽂件信息
*
* @param bucketName bucket名称
* @param objectName ⽂件名称
* @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#statObject
*/
public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {
return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/**
* 删除⽂件
*
* @param bucketName bucket名称
* @param objectName ⽂件名称
* @throws Exception https://docs.minio.io/cn/java-minioClient-apireference.html#removeObject
*/
public void removeObject(String bucketName, String objectName) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/***
* 上传视频
* @param file
* @param bucketName
* @return
* @throws Exception
*/
public UploadResponse uploadVideo(MultipartFile file, String bucketName) throws Exception {
//判断文件是否为空
if (null == file || 0 == file.getSize()) {
return null;
}
//判断存储桶是否存在 不存在则创建
createBucket(bucketName);
//文件名
String originalFilename = file.getOriginalFilename();
//新的文件名 = 时间戳_随机数.后缀名
assert originalFilename != null;
long now = System.currentTimeMillis() / 1000;
String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +
originalFilename.substring(originalFilename.lastIndexOf("."));
//开始上传
log.info("file大小:{}",file.getSize());
minioClient.putObject(
PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
file.getInputStream(), file.getSize(), -1)
.contentType("video/mp4")
.build());
String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;
String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;
return new UploadResponse(url, urlHost);
}
}
测试上传文件 Controller
package com.sqm.minio_demo.controller;
import com.sqm.minio_demo.entity.ResultData;
import com.sqm.minio_demo.entity.UploadResponse;
import com.sqm.minio_demo.util.MinioUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@Slf4j
public class TestController {
@Autowired
private MinioUtil minioUtil;
/**
* @author: xx
* @date: 2022/5/25 15:32
* @description: 上传文件
*/
@PostMapping("/upload")
public ResultData minioUpload(@RequestParam(value = "file") MultipartFile file){
UploadResponse response = null;
try {
response = minioUtil.uploadFile(file, "bucket01");
} catch (Exception e) {
log.error("上传失败",e);
}
return ResultData.ok(response);
}
/**
* @author: xx
* @date: 2022/5/25 15:32
* @description: 上传视频
*/
@PostMapping("/uploadVideo")
public ResultData uploadVideo(@RequestParam(value = "file") MultipartFile file){
UploadResponse response = null;
try {
response = minioUtil.uploadVideo(file, "video-test");
} catch (Exception e) {
log.error("上传失败",e);
}
return ResultData.ok(response);
}
}
测试上传
控制台也可以看到上传的视频
总结
到此这篇关于SpringBoot整合Minio实现上传文件的文章就介绍到这了,更多相关SpringBoot整合Minio上传文件内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!
本文标题为:SpringBoot整合Minio实现上传文件的完整步骤记录
基础教程推荐
- Java实现查找文件和替换文件内容 2023-04-06
- Java并发编程进阶之线程控制篇 2023-03-07
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- java基础知识之FileInputStream流的使用 2023-08-11
- java实现多人聊天系统 2023-05-19
- Java数据结构之对象比较详解 2023-03-07
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- Java实现线程插队的示例代码 2022-09-03
- springboot自定义starter方法及注解实例 2023-03-31
- Java文件管理操作的知识点整理 2023-05-19