SpringBoot项目集成Minio
一、Minio的下载安装以及基本使用
1.下载地址:https://dl.min.io/server/minio/release/windows-amd64/minio.exe
2.下载好后需要手动创建【data】文件夹用于存储Minio中的数据
3.在对应文件路径处,键入【cmd】 后设置Minio的一些变量(第一次启动需要配置)
set MINIO_ROOT_USER=admin set MINIO_ROOT_PASSWORD=admin123 set MINIO_ACCESS_KEY=admin set MINIO_SECRET_KEY=admin123
5.下面是我踩的坑,如果只设置了MINIO_ROOT_USER和MINIO_ROOT_PASSWORD的值,而不设置MINIO_ACCESS_KEY和MINIO_SECRET_KEY的值,当启动minio服务的时候就会报以下异常:
6. 启动minio服务
minio.exe server data
7.进入登录页面后,输入对应的用户名和密码,也就是之前设置的MINIO_ROOT_USER和MINIO_ROOT_PASSWORD的值。
8. 进入主界面后,点击左侧导航栏中的Buckets,然后点击Create Bucket。
9.进入该桶,点击upload,上传一个文件
10.点击左侧导航栏中的Buckets,进入该桶,修改权限为public,这样外界就可以访问上传的文件了。
桶的默认权限是private,所以外界访问不到,需要修改访问权限为public,但是要注意安全问题
二. springboot集成minio
1.引入依赖
<dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.0.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </dependency>
2.编写配置文件
server:
port: 8080
spring:
# 配置文件上传大小限制
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB
minio:
host: http://127.0.0.1:9000 # 访问地址
url: ${minio.host}/${minio.bucket}/ # 对象存储服务的url
access-key: minioadmin # 登录账号
secret-key: minioadmin # 登录账号密码
bucketName: test-bucket # 文件桶的名称
bucket: public // 权限
3.编写minio配置类
@Configuration public class MinIoClientConfig { /** * minio配置 */ @Value("${minio.url}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.bucketName}") private String bucketName; /** * 注入minio客户端 * * @return minio客户端对象 */ @Bean public MinioClient minioClient() { return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build(); } }
4.编写minio工具类
package com.xuyaxu.until; import com.xuyaxu.entity.Fileinfo; import io.minio.*; import io.minio.http.Method; import io.minio.messages.Bucket; import io.minio.messages.Item; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.io.InputStream; import java.util.ArrayList; import java.util.List; @Component public class MinioUtil { /** * minio配置 */ @Value("${minio.url}") private String endpoint; @Autowired private MinioClient minioClient; /** * 创建一个桶 */ public void createBucket(String bucket) throws Exception { boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build()); if (!found) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build()); } } /** * 上传一个文件 */ public String uploadFile(InputStream stream, String bucket, String objectName) throws Exception { ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName) .stream(stream, -1, 10485760).build()); return endpoint + "/" + bucket + "/" + objectWriteResponse.object(); } /** * 列出所有的桶 */ public List<String> listBuckets() throws Exception { List<Bucket> list = minioClient.listBuckets(); List<String> names = new ArrayList<>(); list.forEach(b -> { names.add(b.name()); }); return names; } /** * 列出一个桶中的所有文件和目录 */ public List<Fileinfo> listFiles(String bucket) throws Exception { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucket).recursive(true).build()); List<Fileinfo> infos = new ArrayList<>(); results.forEach(r->{ Fileinfo info = new Fileinfo(); try { Item item = r.get(); info.setFilename(item.objectName()); info.setDirectory(item.isDir()); info.setFilepath(endpoint+"/"+bucket+"/"+item.objectName()); infos.add(info); } catch (Exception e) { e.printStackTrace(); } }); return infos; } /** * 下载一个文件 */ public InputStream download(String bucket, String objectName) throws Exception { InputStream stream = minioClient.getObject( GetObjectArgs.builder().bucket(bucket).object(objectName).build()); return stream; } /** * 删除一个桶 */ public void deleteBucket(String bucket) throws Exception { minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build()); } /** * 删除一个对象 */ public void deleteObject(String bucket, String objectName) throws Exception { minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build()); } /** * 复制文件 */ public void copyObject(String sourceBucket, String sourceObject, String targetBucket, String targetObject) throws Exception { this.createBucket(targetBucket); minioClient.copyObject(CopyObjectArgs.builder().bucket(targetBucket).object(targetObject) .source(CopySource.builder().bucket(sourceBucket).object(sourceObject).build()).build()); } /** * 获取文件信息 */ public String getObjectInfo(String bucket, String objectName) throws Exception { return minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build()).toString(); } /** * 生成一个给HTTP GET请求用的presigned URL。 * 浏览器/移动端的客户端可以用这个URL进行下载, * 即使其所在的存储桶是私有的。 */ public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception { GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs .builder().bucket(bucketName).object(objectName).expiry(expires).method(Method.GET).build(); return minioClient.getPresignedObjectUrl(build); } /** * 获取minio中所有的文件 */ public List<Fileinfo> listAllFile() throws Exception { List<String> list = this.listBuckets(); List<Fileinfo> fileinfos = new ArrayList<>(); for (String bucketName : list) { fileinfos.addAll(this.listFiles(bucketName)); } return fileinfos; } }
5.编写文件实体类
@Data public class Fileinfo { String filename; String filepath; Boolean directory; }
6.编写接口响应实体
@Data public class ResultData<T> { public static final Integer SUCCESS_CODE = 200; public static final Integer FAIL_CODE = 4000; public static final String SUCCESS_MESSAGE = "操作成功"; public static final String FAIL_MESSAGE = "操作失败"; /** * 返回状态码 */ private Integer code; /** * 返回信息 */ private String message; /** * 返回数据 */ private T data; public ResultData() { } public static <T> ResultData<T> success() { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(SUCCESS_CODE); resultUtil.setMessage(SUCCESS_MESSAGE); return resultUtil; } public static <T> ResultData<T> success(T data) { ResultData<T> resultUtil = success(); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> success(String message, T data) { ResultData<T> resultUtil = success(); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> success(Integer code, String message, T data) { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(code); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> success(Integer code, String message,Integer count, T data) { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(code); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> fail() { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(FAIL_CODE); resultUtil.setMessage(FAIL_MESSAGE); return resultUtil; } public static <T> ResultData<T> fail(T data) { ResultData<T> resultUtil = fail(); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> fail(String message, T data) { ResultData<T> resultUtil = fail(); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> fail(Integer code, String message) { ResultData<T> resultUtil = fail(); resultUtil.setCode(code); resultUtil.setMessage(message); return resultUtil; } public static <T> ResultData<T> fail(Integer code, String message, T data) { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(code); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public void setCode(int code){ this.code = code; } public int getCode(){ return this.code; } public void setMessage(String message){ this.message = message; } public String getMessage(){ return message; } public void setData(T data){ this.data = data; } public T getData(){ return data; } }
7.创建minio控制器
package com.xuyaxu.controller; import com.xuyaxu.config.ResultData; import com.xuyaxu.entity.Fileinfo; import com.xuyaxu.until.MinioUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; import java.util.List; /** * minio相关接口 * * @author songwp * @date 2024/10/31 17:51 */ @RestController @RequestMapping("minio") public class MinioController { @Autowired MinioUtil minioUtil; /** * 文件上传 * * @param file 文件 * @param bucket 桶名 * @param objectName 对象名 * @return 是否成功 * @throws Exception */ @RequestMapping(value = "/upload", method = RequestMethod.POST) public ResultData upload(@RequestParam("file") MultipartFile file, @RequestParam ("bucket") String bucket, @RequestParam(required = false) String objectName) throws Exception { String filePath =""; minioUtil.createBucket(bucket); if (objectName != null) { filePath = minioUtil.uploadFile(file.getInputStream(), bucket, objectName + "/" + file.getOriginalFilename()); } else { filePath =minioUtil.uploadFile(file.getInputStream(), bucket, file.getOriginalFilename()); } return ResultData.success(filePath); } /** * 获取文件信息 * @param bucket 桶名 * @return 是否成功 */ @RequestMapping(value = "/getFile", method = RequestMethod.GET) public ResultData getFile(@RequestParam ("bucket")String bucket){ try { List<Fileinfo> fileinfos = minioUtil.listFiles(bucket); return ResultData.success(fileinfos); } catch (Exception e) { throw new RuntimeException(e); } } /** * 文件下载 * * @param bucket 桶名 * @param objectName 对象名 * @return 是否成功 */ @GetMapping("download") public ResultData download(@RequestParam("bucket") String bucket, @RequestParam("objectName") String objectName){ try { InputStream download = minioUtil.download(bucket, objectName); return ResultData.success(); } catch (Exception e) { throw new RuntimeException(e); } } /** * 获取文件信息 * * @param bucket 桶名 * @param objectName 对象名 * @return 是否成功 */ @GetMapping("getObjectInfo") public ResultData getObjectInfo(@RequestParam("bucket") String bucket, @RequestParam("objectName") String objectName) throws Exception { String objectInfo = minioUtil.getObjectInfo(bucket, objectName); String objectStat = objectInfo.replaceAll("ObjectStat", ""); return ResultData.success(objectStat); } /** * 生成一个给HTTP GET请求用的presigned URL。 * * @param bucket 桶名 * @param objectName 对象名 * @return 是否成功 */ @GetMapping("getObjectUrl") public ResultData getObjectUrl(@RequestParam("bucket") String bucket, @RequestParam("objectName") String objectName) throws Exception { String url = minioUtil.getPresignedObjectUrl(bucket, objectName,7200); return ResultData.success(url); } /** * 列出所有的桶 */ @RequestMapping(value = "/listBuckets", method = RequestMethod.GET) public ResultData listBuckets() throws Exception { return ResultData.success(minioUtil.listBuckets()); } /** * 获取minio中所有的文件 */ @RequestMapping(value = "/listAllFile", method = RequestMethod.GET) public ResultData listAllFile() throws Exception { return ResultData.success(minioUtil.listAllFile()); } }
8.通过apiPost调用接口具体实例
9.最后查看test-bucket桶中是否有刚才上传的文件就可以了。如果有则表明你的项目已经成功集成minio了
以上是我对SpringBoot集成Minio的简单的总结,我这里只展示了上传的方法,有不到之处敬请大家批评指正!
古今成大事者,不唯有超世之才,必有坚韧不拔之志!