minio 上传、下载和删除案例
2025年4月9日大约 2 分钟
引入maven依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
文件的上传、下载、删除操作
import io.minio.*;
import io.minio.errors.ErrorResponseException;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
public class Main {
public static void main(String[] args) {
String fileName = "1715759535550.jpg";
Path path = Paths.get("E:\\BaiduNetdiskDownload\\minio\\" + fileName);
String bucketName = "test";
try (FileInputStream fileInputStream = new FileInputStream(path.toString())) {
//1.创建minio链接客户端 accessKey: minio账号 secretKey: minio密码 endpoint: 文件上传地址
MinioClient minioClient = MinioClient.builder().credentials("minioadmin", "minioadmin").endpoint("http://127.0.0.1:9000/").build();
//2.上传
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
//文件名
.object(fileName)
//文件类型
.contentType("application/vnd.openxmlformats-officedocument.presentationml.presentation")
//桶名词 与minio创建的名词一致
.bucket(bucketName)
//文件流
.stream(fileInputStream, fileInputStream.available(), -1)
.build();
minioClient.putObject(putObjectArgs);
System.out.println("文件上传成功");
// ======================================================================================
GetObjectArgs build = GetObjectArgs.builder()
.object(fileName)
.bucket(bucketName)
.build();
InputStream object = minioClient.getObject(build);
// 定义本地保存路径
String localFilePath = "E:\\BaiduNetdiskDownload\\minio\\download\\" + fileName;
// 使用NIO进行高效文件写入
Files.copy(object, Paths.get(localFilePath), StandardCopyOption.REPLACE_EXISTING);
System.out.println("文件下载成功,保存路径:" + localFilePath);
// ==============================================================================================
if (!objectExists(minioClient, bucketName, fileName)) {
System.out.println("文件不存在,无需删除");
return;
}
RemoveObjectArgs removeArgs = RemoveObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.build();
minioClient.removeObject(removeArgs);
if (objectExists(minioClient, bucketName, fileName)) {
throw new RuntimeException("文件删除失败,仍可检测到对象");
}
System.out.println("文件删除成功");
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 验证对象是否存在
private static boolean objectExists(MinioClient client, String bucket, String object) {
try {
client.statObject(StatObjectArgs.builder()
.bucket(bucket)
.object(object)
.build());
return true;
} catch (ErrorResponseException e) {
if ("NoSuchKey".equals(e.errorResponse().code())) {
return false;
}
throw new RuntimeException("对象状态检查失败", e);
} catch (Exception e) {
throw new RuntimeException("对象状态检查异常", e);
}
}
}
关闭延迟问题
在执行完上述代码后,会发现程序要过一段时间才会结束。这是因为其 HTTP 连接池未清理,MinIO 客户端底层使用 OkHttpClient,默认保持连接池存活。可以在 cmd 里面 输入 netstat -aon | findstr 端口
,会发现其监听的端口号存在进程。它关闭后程序才是正式结束。
因此我们自定义 OkHttpClient,手动关闭
// 创建自定义 HTTP 客户端
OkHttpClient customHttpClient = new OkHttpClient.Builder()
.connectionPool(new ConnectionPool(20, 5, TimeUnit.MINUTES))
.build();
// 构建 MinIO 客户端
MinioClient minioClient = MinioClient.builder()
.credentials("admin", "winditCMC2020")
.endpoint("http://10.100.50.217:9002")
.httpClient(customHttpClient)
.build();
//===========程序逻辑================
customHttpClient.dispatcher().executorService().shutdown();
customHttpClient.connectionPool().evictAll();
批量下载问题
minio 不能一次性下载多个文件,只能一个文件一个文件下载。想同时下载多个文件,只能使用多线程。比如使用 parallelStream 。
String LOCAL_DIR = "E:\\BaiduNetdiskDownload\\minio\\download\\";
String remotePath = "wpd/1743153330102/25032817153917958/202503/1/0/";
ArrayList<String> fileList = new ArrayList<>();
fileList.add("1743384078223");
fileList.add("1743369669340");
fileList.parallelStream().forEach(dataName -> {
try {
Path localPath = Paths.get(LOCAL_DIR + dataName);
Files.createDirectories(localPath.getParent());
try (InputStream stream = minioClient.getObject(
GetObjectArgs.builder()
.bucket(bucketName)
.object(remotePath + dataName)
.build())) {
Files.copy(stream, localPath);
System.out.println("下载成功: " + dataName);
}
} catch (Exception e) {
System.err.println("下载失败: " + dataName);
e.printStackTrace();
}
});