第一步:下载miNIO服务安装包 去官网下载:MinIO | 用于创建高性能对象存储的代码和下载内容 minio的使用文档:MinIO Object Storage for Kubernetes — MinIO Object Storag
去官网下载:MinIO | 用于创建高性能对象存储的代码和下载内容
minio的使用文档:MinIO Object Storage for Kubernetes — MinIO Object Storage for Kubernetes
MinIo有两个重要的对象,服务器minio.exe和客户端minio.client。搭建服务器用于接收文件信息,客户端用于上传文件。
官网下载有些慢
记住一点:如果是下载windows版本的,切记千万不能去双击运行,这样可能会导致最终启动失败;无论是windows还是linux都是通过命令启动的。
在windows环境下,在你的minio.exe文件所在位置的文件夹下(最好在同级路径下创建一个类似data的文件夹,用于存储数据),打开cmd命令框,
输入:minio.exe server D:\Java_study\javaEE-study\JAVA\minio\data (后面的数据存储路径文件夹是自定义的)
(如果是linux启动minio服务器,则在对应的minio存放的路径下输入:./minio server ./data)
打开浏览器输入上面的访问地址和端口即可访问minio服务器的ui界面
点开任意一个桶
package com.jdh.minio;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.util.List;import io.minio.*;import io.minio.messages.Bucket;public class FileUploader { public static void main(String[] args) { try { // 创建客户端 Minioclient minioClient = MinioClient.builder()// api地址.endpoint("127.0.0.1",9000,true)//.endpoint("Http://127.0.0.1:9000")// 前面设置的账号密码.credentials("minioadmin", "minioadmin").build(); System.out.println(minioClient); // 检查桶是否存在 boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("test").build()); if (!found) { // 创建桶 minioClient.makeBucket(MakeBucketArgs.builder().bucket("test").build()); } //列出所有桶名 List buckets = minioClient.listBuckets(); for (Bucket i : buckets){ System.out.println(i.name()); } //删除某一个桶// minioClient.removeBucket(// RemoveBucketArgs.builder()//.bucket("桶名称")//.build()); System.out.println("开始你的操作"); File file = new File("D:\\Java_study\\javaEE-study\\user.xlsx"); String fileName = file.getName(); String realFileName = fileName.substring(fileName.lastIndexOf("\\")+1, fileName.lastIndexOf(".")); String fileType = fileName.substring(fileName.lastIndexOf(".")+1); //通过路径上传一个文件 ObjectWriteResponse testDir = minioClient.uploadObject( UploadObjectArgs.builder().bucket("test").object("user_Path1")//文件名字.filename("D:\\Java_study\\javaEE-study\\user.xlsx")//文件存储的路径.contentType(fileType).build()); //通过文件格式上传一个文件 InputStream fileInputStream = new FileInputStream(file); long size = file.length(); minioClient.putObject( PutObjectArgs.builder().bucket("test").object("user_File1").stream(fileInputStream, size, -1).contentType(fileType).build()); //文件下载,都是这种下载到指定路径 minioClient.downloadObject(DownloadObjectArgs.builder() .bucket("test") .object("user") .filename("D:\\Java_study\\javaEE-study\\user_test.xlsx") .build()); } catch (Exception e) { e.printStackTrace(); } }}
此demo演示的是SpringBoot项目整合minio,demo中minio版本是8.0.3,但参考版本最低7.x以上。
demo项目gitee连接:https://gitee.com/java_utils_demo/java_minio_demo.git
(新手别忘记引入springboot的父依赖)
org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-WEB org.springframework.boot spring-boot-starter-test io.minio minio 8.0.3 com.alibaba.fastJSON2 fastjson2 2.0.12 org.projectlombok lombok
下面的配置实际可有可无,只是在创建minio的客户端的时候需要的一些连接服务端的一些相关配置信息
server: port: 8080# Minio配置minio: config: ip: 127.0.0.1 #ip地址 port: 9000 # 端口号 accessKey: minioadmin # 账号 secreTKEy: minioadmin # 密码 secure: false #如果是true,则用的是https而不是http,默认值是true bucketName: "jdh-bucket" # 桶的名字 downloadDir: "/data/excel" #保存到本地的路径
下面配置文件类就是通过spring的ConfigurationProperties注解完成配置文件中相关参数的注入
package com.jdh.minio.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;@Component@Data@ConfigurationProperties(prefix = "minio.config")public class MinioProperties { private String ip; private Integer port; private String accessKey; private String secretKey; private String bucketName; private String downloadDir; private Boolean secure;}
如:获取一个minio连接客户端、文件上下传封装、创建\删除桶、列出所有桶\文件信息等
package com.jdh.minio.config;import io.minio.*;import io.minio.errors.*;import io.minio.http.Method;import io.minio.messages.Bucket;import io.minio.messages.DeleteObject;import io.minio.messages.Item;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.util.StringUtils;import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.security.InvalidKeyException;import java.security.NoSuchAlGorithmException;import java.time.LocalDateTime;import java.time.ZonedDateTime;import java.util.List;import java.util.Map;import java.util.UUID;import java.util.concurrent.TimeUnit;@Configuration@Slf4jpublic class MinioFileUtil { @Resource private MinioProperties minioProperties; private MinioClient minioClient; // @Bean// public MinioClient getMinioClient(){//// String url = "http:" + minioProperties.getIp() + ":" + minioProperties.getPort();//// try {// return new MinioClient(url, minioProperties.getAccessKey(), minioProperties.getSecretKey());// } catch (InvalidEndpointException | InvalidPortException e) {// e.printStackTrace();// log.info("-----创建Minio客户端失败-----");// return null;// }// } @Bean public MinioClient getClient() { String url = "http:" + minioProperties.getIp() + ":" + minioProperties.getPort(); MinioClient minioClient = MinioClient.builder() .endpoint(url) //两种都可以,这种全路径的其实就是下面分开配置一样的// .endpoint(minioProperties.getIp(),minioProperties.getPort(),minioProperties.getSecure()) .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey()) .build(); this.minioClient = minioClient; return minioClient; } public void createBucket(String bucketName) throws Exception { if (!StringUtils.hasLength(bucketName)) { throw new RuntimeException("创建桶的时候,桶名不能为空!"); } // Create bucket with default region. minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } public void createBucketByRegion(String bucketName, String region) throws Exception { if (!StringUtils.hasLength(bucketName)) { throw new RuntimeException("创建桶的时候,桶名不能为空!"); } MinioClient minioClient = this.getClient(); // Create bucket with specific region. minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .region(region) // .build());// // Create object-lock enabled bucket with specific region.// minioClient.makeBucket(// MakeBucketArgs.builder()// .bucket("my-bucketname")// .region("us-west-1")// .objectLock(true)// .build()); } public void renameBucket(String oldBucketName, String newBucketName) throws Exception { if (!StringUtils.hasLength(oldBucketName) || !StringUtils.hasLength(newBucketName)) { throw new RuntimeException("修改桶名的时候,桶名不能为空!"); } } public void deleteBucket(String bucketName) throws Exception { if (!StringUtils.hasLength(bucketName)) { throw new RuntimeException("删除桶的时候,桶名不能为空!"); } minioClient.removeBucket( RemoveBucketArgs.builder() .bucket(bucketName) .build()); } public boolean checkBucketExist(String bucketName) throws Exception { if (!StringUtils.hasLength(bucketName)) { throw new RuntimeException("检测桶的时候,桶名不能为空!"); } return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } public List getAllBucketInfo() throws Exception { //列出所有桶 List buckets = minioClient.listBuckets(); return buckets; } public Iterable> getBucketAllFile(String bucketName, String folderName, Boolean isDeep) throws Exception { if (!StringUtils.hasLength(bucketName)) { throw new RuntimeException("获取桶中文件列表的时候,桶名不能为空!"); } if (!StringUtils.hasLength(folderName)) { folderName = ""; } System.out.println(folderName); Iterable> listObjects = minioClient.listObjects( ListObjectsArgs .builder() .bucket(bucketName) .prefix(folderName + "/") .recursive(isDeep) .build());// for (Result- result : listObjects) {// Item item = result.get();// System.out.println(item.objectName());// } return listObjects; } public Boolean deleteBucketFile(String bucketName, String objectName) { if (!StringUtils.hasLength(bucketName) || !StringUtils.hasLength(objectName)) { throw new RuntimeException("删除文件的时候,桶名或文件名不能为空!"); } try { minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); return true; } catch (Exception e) { log.info("删除文件失败"); return false; } } public Boolean deleteBucketFolder(String bucketName, String objectName, Boolean isDeep) { if (!StringUtils.hasLength(bucketName) || !StringUtils.hasLength(objectName)) { throw new RuntimeException("删除文件夹的时候,桶名或文件名不能为空!"); } try { ListObjectsArgs args = ListObjectsArgs.builder().bucket(bucketName).prefix(objectName + "/").recursive(isDeep).build(); Iterable
> listObjects = minioClient.listObjects(args); listObjects.forEach(objectResult -> { try { Item item = objectResult.get(); minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(item.objectName()).build()); } catch (Exception e) { log.info("删除文件夹中的文件异常", e); } }); return true; } catch (Exception e) { log.info("删除文件夹失败"); return false; } } public String getFileDownloadUrl(String bucketName, String objectName, Integer expires) throws Exception { GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() .method(Method.GET)//下载地址的请求方式 .bucket(bucketName) .object(objectName) .expiry(expires, TimeUnit.SECONDS)//下载地址过期时间 .build(); String objectUrl = minioClient.getPresignedObjectUrl(args); return objectUrl; } public String getFileUploadUrl(String bucketName, String objectName, Integer expires) throws Exception { // 过期时间 ZonedDateTime zonedDateTime = ZonedDateTime.now().plusSeconds(60); PostPolicy postPolicy = new PostPolicy(bucketName, zonedDateTime); // 获取对象的默认权限策略 StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build()); String objectPolicy = statObjectResponse.headers().get("x-amz-object-policy"); String presignedObjectUrl = minioClient.getPresignedObjectUrl( GetPresignedObjectUrlArgs.builder() .bucket(bucketName) .object(objectName) .method(Method.POST) .expiry(expires) // 预签名的 URL 有效期为 1 小时 .build()); MyMinioClient client = new MyMinioClient(minioClient); return presignedObjectUrl; } public ObjectWriteResponse createBucketFolder(String bucketName, String folderName) throws Exception { if (!checkBucketExist(bucketName)) { throw new RuntimeException("必须在桶存在的情况下才能创建文件夹"); } if (!StringUtils.hasLength(folderName)) { throw new RuntimeException("创建的文件夹名不能为空"); } PutObjectArgs putObjectArgs = PutObjectArgs.builder() .bucket(bucketName) .object(folderName + "/") .stream(new ByteArrayInputStream(new byte[0]), 0, 0) .build(); ObjectWriteResponse objectWriteResponse = minioClient.putObject(putObjectArgs); return objectWriteResponse; } public boolean getBucketFileExist(String objectName, String bucketName) throws Exception { if (!StringUtils.hasLength(objectName) || !StringUtils.hasLength(bucketName)) { throw new RuntimeException("检测文件的时候,文件名和桶名不能为空!"); } try { // 判断文件是否存在 boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()) && minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build()) != null; return exists; } catch (ErrorResponseException e) { log.info("文件不存在 ! Object does not exist"); return false; } catch (Exception e) { throw new Exception(e); } } public Boolean checkBucketFolderExist(String bucketName, String objectName, Boolean isDeep) { Iterable> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(isDeep).build()); return results.iterator().hasNext(); // 文件夹下存在文件 } public boolean uploadFile(MultipartFile file, String bucketName) throws Exception { if (file == null || file.getSize() == 0 || file.isEmpty()) { throw new RuntimeException("上传文件为空,请重新上传"); } if (!StringUtils.hasLength(bucketName)) { log.info("传入桶名为空,将设置默认桶名:" + minioProperties.getBucketName()); bucketName = minioProperties.getBucketName(); if (!this.checkBucketExist(minioProperties.getBucketName())) { this.createBucket(minioProperties.getBucketName()); } } if (!this.checkBucketExist(bucketName)) { throw new RuntimeException("当前操作的桶不存在!"); } // 获取上传的文件名 String filename = file.getOriginalFilename(); assert filename != null; //可以选择生成一个minio中存储的文件名称 String minioFilename = UUID.randomUUID().toString() + "_" + filename; String url = "http:" + minioProperties.getIp() + ":" + minioProperties.getPort(); InputStream inputStream = file.getInputStream(); long size = file.getSize(); String contentType = file.getContentType(); // Upload known sized input stream. minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) //上传到指定桶里面 .object(minioFilename)//文件在minio中存储的名字 //p1:上传的文件流;p2:上传文件总大小;p3:上传的分片大小 .stream(inputStream, size, -1) //上传分片文件流大小,如果分文件上传可以采用这种形式 .contentType(contentType) //文件的类型 .build()); return this.getBucketFileExist(minioFilename, bucketName); } public boolean uploadPath(String filePath, String bucketName) throws Exception { File file = new File(filePath); if (!file.isFile()) { throw new RuntimeException("上传文件为空,请重新上传"); } if (!StringUtils.hasLength(bucketName)) { log.info("传入桶名为空,将设置默认桶名:" + minioProperties.getBucketName()); bucketName = minioProperties.getBucketName(); if (!this.checkBucketExist(minioProperties.getBucketName())) { this.createBucket(minioProperties.getBucketName()); } } if (!this.checkBucketExist(bucketName)) { throw new RuntimeException("当前操作的桶不存在!"); } String minioFilename = UUID.randomUUID().toString() + "_" + file.getName();//获取文件名称 String fileType = minioFilename.substring(minioFilename.lastIndexOf(".") + 1); minioClient.uploadObject( UploadObjectArgs.builder() .bucket(bucketName) .object(minioFilename)//文件存储在minio中的名字 .filename(filePath)//上传本地文件存储的路径 .contentType(fileType)//文件类型 .build()); return this.getBucketFileExist(minioFilename, bucketName); } public void downloadFile(HttpServletResponse response, String bucketName, String objectName) throws Exception { if (response == null || !StringUtils.hasLength(bucketName) || !StringUtils.hasLength(objectName)) { throw new RuntimeException("下载文件参数不全!"); } if (!this.checkBucketExist(bucketName)) { throw new RuntimeException("当前操作的桶不存在!"); } //获取一个下载的文件输入流操作 GetObjectResponse objectResponse = minioClient.getObject( GetObjectArgs.builder() .bucket(bucketName) .object(objectName) .build()); OutputStream outputStream = response.getOutputStream(); int len = 0; byte[] buf = new byte[1024 * 8]; while ((len = objectResponse.read(buf)) != -1) { outputStream.write(buf, 0, len); } if (outputStream != null) { outputStream.close(); outputStream.flush(); } objectResponse.close(); } public void downloadPath(String downloadPath, String bucketName, String objectName) throws Exception { if (downloadPath.isEmpty() || !StringUtils.hasLength(bucketName) || !StringUtils.hasLength(objectName)) { throw new RuntimeException("下载文件参数不全!"); } if (!new File(downloadPath).isDirectory()) { throw new RuntimeException("本地下载路径必须是一个文件夹或者文件路径!"); } if (!this.checkBucketExist(bucketName)) { throw new RuntimeException("当前操作的桶不存在!"); } downloadPath += objectName; minioClient.downloadObject( DownloadObjectArgs.builder() .bucket(bucketName) //指定是在哪一个桶下载 .object(objectName)//是minio中文件存储的名字;本地上传的文件是user.xlsx到minio中存储的是user-minio,那么这里就是user-minio .filename(downloadPath)//需要下载到本地的路径,一定是带上保存的文件名;如 d:\\minio\\user.xlsx .build()); }}
可以在controller中写http接口来进行验证,本文采用的单元测试进行验证。
package com.jdh.minio.config;import io.minio.*;import io.minio.messages.Bucket;import io.minio.messages.Item;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.mock.web.MockMultipartFile;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.multipart.commons.CommonsMultipartFile;import java.io.*;import java.util.List;import static org.junit.jupiter.api.Assertions.*;@SpringBootTestclass MinioFileUtilTest { @Autowired private MinioFileUtil minioFileUtil; @Test void createBucket() throws Exception { minioFileUtil.createBucket("minio-file"); boolean minioFile = minioFileUtil.checkBucketExist("minio-file"); System.out.println(minioFile); } @Test void createBucketByRegion() throws Exception { minioFileUtil.createBucketByRegion("minio-file", "minio-region"); boolean minioFile = minioFileUtil.checkBucketExist("minio-file"); System.out.println(minioFile); } @Test void deleteBucket() throws Exception { minioFileUtil.deleteBucket("minio-file"); boolean minioFile = minioFileUtil.checkBucketExist("minio-file"); System.out.println(minioFile); } @Test void checkBucketExist() throws Exception { boolean test = minioFileUtil.checkBucketExist("test"); System.out.println(test); } @Test void getAllBucketInfo() throws Exception { List allBucketName = minioFileUtil.getAllBucketInfo(); allBucketName.forEach(e -> System.out.println(e.name())); } @Test void getBucketAllFile() throws Exception { Iterable> allFile = minioFileUtil.getBucketAllFile("minio-folder", "part", true); for (Result- result : allFile) { Item item = result.get(); System.out.println(item.objectName()); } } @Test void getBucketFileExist() throws Exception { boolean fileExist = minioFileUtil.getBucketFileExist("8aa570f9-53f5-4cb5-a0d1-c122ef4e3f89_出师表.docx", "minio-bucket"); System.out.println(fileExist); } @Test void deleteBucketFile() throws Exception { Boolean b = minioFileUtil.deleteBucketFile("minio-folder", "出师表.docx"); System.out.println(b); } @Test void deleteBucketFolder() throws Exception { boolean b = minioFileUtil.deleteBucketFolder("minio-folder", "tempFile", true); System.out.println(b); } @Test void getFileDownloadUrl() throws Exception { String fileUrl = minioFileUtil.getFileDownloadUrl("minio-bucket", "出师表.docx", 60); System.out.println(fileUrl); } @Test void getFileUploadUrl() throws Exception { String fileUrl = minioFileUtil.getFileUploadUrl("minio-bucket", "出师表1.docx", 3600); System.out.println(fileUrl); } @Test void createBucketFolder() throws Exception { String buckName = "minio-bucket"; String folderName = "part"; ObjectWriteResponse bucketFolder = minioFileUtil.createBucketFolder(buckName, folderName); } @Test void checkBucketFolderExist() throws Exception { Boolean tempFile = minioFileUtil.checkBucketFolderExist("minio-bucket", "down", true); System.out.println(tempFile); } @Test void uploadFile() throws Exception { File file = new File("D:\\file\\出师表.docx"); FileInputStream fileInputStream = new FileInputStream(file); String fileName = file.getName(); MockMultipartFile multipartFile = new MockMultipartFile(fileName, fileName, "docx", fileInputStream); boolean uploadFile = minioFileUtil.uploadFile(multipartFile, "minio-folder"); System.out.println(uploadFile); } @Test void uploadPath() throws Exception { boolean uploadPath = minioFileUtil.uploadPath("D:\\file\\出师表.docx", "minio-bucket"); System.out.println(uploadPath); } @Test void downloadFile() { //这里可以使用模拟请求来验证 } @Test void downloadPath() throws Exception { MinioClient client = minioFileUtil.getClient(); minioFileUtil.downloadPath("D:\\file\\", "minio-bucket", "8aa570f9-53f5-4cb5-a0d1-c122ef4e3f89_出师表.docx"); }}
通过访问minio的服务端界面查看功能是否验证通过
来源地址:https://blog.csdn.net/qq_45778079/article/details/131572131
--结束END--
本文标题: minio的基本使用——java
本文链接: https://lsjlt.com/news/387939.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-04-01
2024-04-03
2024-04-03
2024-01-21
2024-01-21
2024-01-21
2024-01-21
2023-12-23
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0