1.在Linux中通过docker中拉取minio镜像
docker pull bitnami/minio
可以使用docker images 查看是否有minio镜像,如果有说明已经获取minio镜像了
2.创建一个文件用于存储MinIO的数据
mkdir -p /minio/data
给该文件赋予完全开放的权限
chmod -R 777 minio/data
3.启动及配置 MinIo
docker run -it -d --name minio -p 9000:9000 -p 9001:9001 -v /minio/data:/data -e MINIO_ROOT_USER="minio_root" -e MINIO_ROOT_PASSWORD="minio_123456" bitnami/minio:latest
4.通过日志查看MinIo
docker logs -f minio
5.在window中访问图中的url,切记,切记浏览器访问端口9001,java API端口是9000
访问的url为 虚拟机的ip地址:9001
6.创建自己的Buckets
7.设置Buckets权限为public
8.生成密钥
导入MinIO依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.2</version>
</dependency>
配置yml文件
minio:
endpoint: http://xxx:9000 #Minio服务所在地址
bucketName: test-minio #存储桶名称
accessKey: minio_root #访问的key,也可以是上面创建的AccessKey
secretKey: minio_123456 #访问的秘钥,也可以是上面创建的SecretKey
upload: test #文件上传路径
MinIOConfig配置类
@Configuration
public class MinIOConfig implements InitializingBean {
@Value("${minio.endpoint}")
private String minio_endpoint;
@Value("${minio.accessKey}")
private String minio_accessKey;
@Value("${minio.secretKey}")
private String minio_secretKey;
@Value("${minio.bucketName}")
private String minio_bucketName;
@Value("${minio.upload}")
private String minio_upload;
public static String MINIO_END_POINT;
public static String MINIO_ACCESS_KEY;
public static String MINIO_SECRET_KEY;
public static String MINIO_BUCKET_NAME;
public static String MINIO_UPLOAD;
@Override
public void afterPropertiesSet() throws Exception {
MINIO_END_POINT = minio_endpoint;
MINIO_ACCESS_KEY = minio_accessKey;
MINIO_SECRET_KEY = minio_secretKey;
MINIO_BUCKET_NAME = minio_bucketName;
MINIO_UPLOAD=minio_upload;
}
}
文件上传的controller层:
@Autowired
private FileStrategy fileStrategy;
@PostMapping("upload")
@ApiOperation(value = "文件上传")
public Result<Url> upload(MultipartFile file) throws Exception{
Result result=new Result();
try {
log.info("upload-------------------------------");
if(null != file){
if(file.getOriginalFilename().contains("mp4")){
//如果上传的视频,校验大小不能超过2M
if(file.getSize()>2048*1024){
result= new Result(CoReturnFormat.MP4_FILE_NOT_2M);
return result;
}
}
String url=fileStrategy.upload(file);
//fileUploadService.uploadFile(file.getOriginalFilename(),file.getInputStream(),file.getSize());
result=new Result(new Url(url),CoReturnFormat.SUCCESS);
}
return result;
} catch (Exception e) {
log.error("upload fail " + e.getMessage(), e);
}
return result;
}
FileStrategy:
public interface FileStrategy {
String upload(MultipartFile file) throws Exception;
}
MinIOAutoConfigure:
@Configuration
@Slf4j
@ConditionalOnProperty(name = "upload.type", havingValue = "MIN")
public class MinIOAutoConfigure {
@Service
public class MinIOServiceImpl implements FileStrategy{
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
@Override
public String upload(MultipartFile file) throws Exception {
String filename = file.getOriginalFilename();
InputStream in = file.getInputStream();
long size = file.getSize();
log.info("filename {} size {}", filename, size);
Objects.requireNonNull(filename);
filename = filename.replaceAll(" ", "");
String fileName= MinIOConfig.MINIO_UPLOAD;
// 创建MinioClient实例。
MinioClient minioClient = MinioClient.builder().endpoint(MinIOConfig.MINIO_END_POINT).credentials(MinIOConfig.MINIO_ACCESS_KEY, MinIOConfig.MINIO_SECRET_KEY).build();
String dateStr = format.format(new Date());
//创建文件路径
String fileUrl = fileName+"/"+(dateStr + "/" + UUID.randomUUID().toString().replace("-","") + "_" + filename);
InputStream inputStream=in;
if(size>5*1024*1024){
//大于5M就压缩
if(filename.contains("jpg")||filename.contains("png")){
//如果是图片,压缩一下
inputStream = ImageUtil.compressImg(in, 1.1f);
}
}
// 上传网络流。
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(MinIOConfig.MINIO_BUCKET_NAME).object(fileUrl)
.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
//文件名称相同会覆盖
minioClient.putObject(objectArgs);
if (inputStream != null) {
inputStream.close();
}
if (in != null) {
in.close();
}
return MinIOConfig.MINIO_END_POINT+ "/" + MinIOConfig.MINIO_BUCKET_NAME + "/" + fileUrl;
}
}
实现文件上传到minIO的主要代码就是putObject()方法
它需要我们创建一个新的
PutObjectArgs
对象的构建器(Builder),用于设置上传文件所需的参数
.bucket(MinIOConfig.MINIO_BUCKET_NAME)
:设置要上传到的MinIO存储桶(bucket)的名称
.object(fileUrl)
:设置要上传的对象(文件)的名称,表示文件在存储桶中的路径和名称。
.stream(file.getInputStream(), file.getSize(), -1)
:设置文件的输入流、文件大小以及超时时间。
file.getInputStream()
获取文件的输入流,
file.getSize()
获取文件的大小,
-1
表示使用默认的超时时间。
.contentType(file.getContentType())
:设置文件的内容类型
运行项目报错:
Caused by: java.lang.RuntimeException: Unsupported OkHttp library found. Must use okhttp >= 4.8.1 at io.minio.S3Base.<clinit>(S3Base.java:106) ... 50 common frames omitted Caused by: java.lang.NoSuchMethodError: kotlin.collections.ArraysKt.copyInto([B[BIII).............
问题需要将okhttp升级4.8.1以上版本
将okhttp升级到4.8.1版本后,还是不行,这时候就要思考是不是okhttp的版本冲突导致,可以通过下载Maven help插件看依赖树,我们可以注意到了报错信息中的NoSuchMethodError: kotlin.collections.ArraysKt.copyInto通过搜索kotlin
发现两个kotlin出现版本不同的问题,所以ArraysKt中找不到copyInto方法。
解决方法:
在 minio 的依赖中排除 okhttp 依赖,再单独引入所需的 okhttp 依赖。在引入的 okhttp 的依赖中排除 kotlin 的依赖,再单独引入所需 kotlin 依赖。
<dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.5.2</version> <exclusions> <exclusion> <artifactId>okhttp</artifactId> <groupId>com.squareup.okhttp3</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.8.1</version> <exclusions> <exclusion> <artifactId>kotlin-stdlib</artifactId> <groupId>org.jetbrains.kotlin</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib</artifactId> <version>1.3.70</version> </dependency>
详细可以看springboot引入minio导致的okhttp、kotlin的版本冲突问题_io.minio.s3base.(s3base.java:104)-CSDN博客
如果出现Non-XML response from server的错误,那就很有可能是在yml文件中端口号配置错误了(浏览器访问端口9001,java API端口是9000),我就是端口之前写错过,找了半天qwq。
接下来重新运行项目,应该就不会报错了
通过debug来了解流程
可以通过前端直接发送请求,也可以用postman发送请求,根据自己的情况来
我们可以看到图片已经上传到minio中了
接下来我们通过访问给前端返回url看是否可以查看图片如果可以,就说明成功了,如果不可以,可能是url写错或者忘记在创建PutObjectArgs时使用contentType(file.getContentType())
好了,以上就是根据我的项目来实现MinIo文件上传功能,以及遇到的一些问题和解决方法,希望对大家有所帮助。
版权归原作者 不会敲码的喵喵 所有, 如有侵权,请联系我们删除。