使用免费的minio代替阿里云oss实现{苍穹外卖-新增菜品-文件上传功能}
`

因为不想付费用阿里云oss,但网上没有搜到现成的修改方案,就自己捣鼓了两天,结合网络资料和deepseek搞成功了,就此分享出来
注意事项
还没看完之后的内容,不清楚是否会和之后内容有冲突,如有冲突可以自己到讲义markdown文件中恢复一下之前的文件内容
步骤一:安装并启动minio
参考的是以下教程:
Windows下Minio的安装以及基本使用https://blog.youkuaiyun.com/qq_35098526/article/details/145041817
minio官方文档-Java 快速入门指南:https://min.io/docs/minio/linux/developers/java/minio-java.html#minio-java-quickstart
minio中文文档https://www.bookstack.cn/read/MinioCookbookZH/21.md#%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8%E7%A4%BA%E4%BE%8B%EF%BC%8D%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0
步骤二:修改pom.xml来添加minio需要的依赖【阿里镜像库中没有minio库,连不上官网的可能需要手动安装依赖,教程可以看最后一个目录里的附加内容】
在sky-take-out和sky-common里的pom.xml中,com.aliyun.oss后面,添加以下依赖:
【一些提示:可能会有java.lang.ClassNotFoundException: okio.Buffer或kotlin.jvm.internal.Intrinsics或Could not initialize class io.minio.MinioAsyncClient类似错误,是因为未成功下载以下依赖。
提前检查该问题的方法:执行查询依赖树并检查冲突的指令(可以检查出来多版本或者未成功按照pom改动下载依赖的问题)mvn dependency:tree
如果发现未成功按照pom改动下载依赖,使用mvn clean install可以解决】
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.17</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.8.21</version> <!-- 使用与 MinIO SDK 兼容的版本 -->
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>3.6.0</version> <!-- 使用与OkHttp兼容的版本 -->
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio-jvm</artifactId>
<version>3.6.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.simpleframework</groupId>
<artifactId>simple-xml</artifactId>
<version>2.7.1</version>
</dependency>
minio相关依赖的知识点:
- MinIO 从 8.5.0+ 开始使用 Kotlin 重写了部分代码,所以想使用带最新功能的MinIO 8.5.x就需要添加Kotlin 依赖
- MinIO Java SDK 内部使用 OkHttp 作为 HTTP 客户端,而 OkHttp 又依赖 Okio 库。当这些依赖没有正确传递或存在版本冲突时,就会出现错误。
依赖关系链:
MinIO SDK → OkHttp → Okio
MinIO SDK (8.5+) → Kotlin
(当时添加了有OkHttp/Okio仍然报错,于是参考stackoverflow的回复又加了okio-jvm3.6.0【参考资料在最后】,又报了simple-xml相关错误,所以又直接加进去了)
参考资料:
java, okhttp, I get these exception: java.lang.NoClassDefFoundError: okio/Buffer, without module not,https://stackoverflow.com/questions/77008227/java-okhttp-i-get-these-exception-java-lang-noclassdeffounderror-okio-buffer
步骤三:修改application-dev.yml
在datasource的同级(如下图位置),添加如下代码
alioss:
endpoint: 当时启动minio时指定的address(比如http://127.0.0.1:9090)
access-key-id: 创建bucket的access-key-id
access-key-secret: 创建bucket的access-key-secret
bucket-name: sky-take-out
步骤四:修改AliOssUtil.java
package com.sky.utils;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.errors.MinioException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
/**
* 文件上传
*
* @param bytes
* @param objectName
* @return
*/
public String upload(byte[] bytes, String objectName) {
// 创建MinioClient实例
MinioClient minioClient = MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKeyId, accessKeySecret)
.build();
try {
// 将字节数组转换为输入流
InputStream inputStream = new ByteArrayInputStream(bytes);
// 创建PutObject请求并上传
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(inputStream, bytes.length, -1) // -1表示不限制流的大小
.build()
);
} catch (MinioException e) {
System.out.println("MinIO server error: " + e.getMessage());
} catch (Exception e) {
System.out.println("An error occurred: " + e.getMessage());
}
//文件访问路径规则 MinIO:http://Endpoint/BucketName/ObjectName
// 确保endpoint以/结尾
if (!endpoint.endsWith("/")) {
endpoint = endpoint + "/";
}
// 处理objectName开头的/,如有就删除以免后面又添加一个构成双斜杠
if (objectName.startsWith("/")) {
//截取字符串从第2个字符开始到末尾的子字符串(即去掉第一个字符)
objectName = objectName.substring(1);
}
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(endpoint)
.append(bucketName)
.append("/")
.append(objectName);
log.info("文件上传到:{}", urlBuilder.toString());
return urlBuilder.toString();
}
}
步骤五:验证是否成功
通过前端菜品管理上传图片后,在minio控制台和苍穹外卖网页中,均可看到自己上传的图片
minio控制台
苍穹外卖网页
附加内容:手动安装maven依赖
参考资料:【maven导入jar包并添加依赖】 https://www.bilibili.com/video/BV1zY4y1m7a2/
起因:添加依赖代码并reload maven changes之后代码飘红,然后找是不是仓库缺依赖包版本的问题,想看一下maven-setting的配的仓库里有什么版本的minio,于是在maven setting中找到其setting.xml路径,并跳到该文件中发现只有阿里镜像,而阿里镜像仓库中没有minio所以要自己手动导入
(找maven的setting文件方法【maven爆红处理方法】 https://www.bilibili.com/video/BV1ke4y1W7bT)
步骤:在maven官方仓库中搜索到所需的依赖jar包(https://mvnrepository.com/artifact/io.minio/minio),下载到本地(如下图,点击jar按钮),再在cmd(管理员版)逐个执行如下maven指令
(可以复制如下代码,修改本地下载路径为你的路径,再逐个在cmd管理员版中运行)
maven下载指令分析:mvn install:install-file -Dfile=你的本地下载路径 -DgroupId=在pom文件中写的groupId -DartifactId=在pom文件中写的artifactId -Dversion=在pom文件中写的版本号 -Dpackaging=jar
注意:本来使用如下方式才可以执行install指令的,但是邪门的是第二天的时候这个方法失效了,必须到cmd(管理员版)里面才能执行成功,powershell都不行
mvn install:install-file -Dfile="D:\Work\Tools\minio\minio-8.5.17.jar" -DgroupId=io.minio -DartifactId=minio -Dversion=8.5.17 -Dpackaging=jar
mvn install:install-file -Dfile="D:\Work\Tools\minio\okhttp-4.12.0.jar" -DgroupId=com.squareup.okhttp3 -DartifactId=okhttp -Dversion=4.12.0 -Dpackaging=jar
mvn install:install-file -Dfile="D:\Work\Tools\minio\kotlin-stdlib-1.8.21.jar" -DgroupId=org.jetbrains.kotlin -DartifactId=kotlin-stdlib -Dversion=1.8.21 -Dpackaging=jar
mvn install:install-file -Dfile="D:\Work\Tools\minio\okio-3.6.0.jar" -DgroupId=com.squareup.okio -DartifactId=okio -Dversion=3.6.0 -Dpackaging=jar
mvn install:install-file -Dfile="D:\Work\Tools\minio\okio-jvm-3.6.0.jar" -DgroupId=com.squareup.okio -DartifactId=okio-jvm -Dversion=3.6.0 -Dpackaging=jar
mvn install:install-file -Dfile="D:\Work\Tools\minio\simple-xml-2.7.1.jar" -DgroupId=org.simpleframework -DartifactId=simple-xml -Dversion=2.7.1 -Dpackaging=jar