package conf.util; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import io.minio.GetObjectArgs; import io.minio.ListObjectsArgs; import io.minio.MinioClient; import io.minio.Result; import io.minio.errors.MinioException; import io.minio.messages.Item; public class DownloadAllFilesFromMinios { public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException, MinioException { // MinIO服务的URL,Access Key和Secret Key String endpoint = ""; //你的minio地址 String accessKey = ""; String secretKey = ""; String bucketName = ""; // 存储桶名称 String localDownloadPath = "G:\\bucket"; // 本地文件夹,只用创建桶,如果你的桶下面还有很多文件夹,代码自动创建 int threadPoolSize = 4; // 根据实际情况调整线程池大小 ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize); List<Future<Void>> futures = new ArrayList<>(); try { // 初始化MinioClient MinioClient minioClient = MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); // 使用ListObjectsArgs正确构建请求来遍历存储桶中的所有对象 Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder() .bucket(bucketName) .recursive(true) // 添加此参数以递归列出所有对象 .build()); for (Result<Item> result : results) { final Item item = result.get(); final String objectName = item.objectName(); final String localPath = Paths.get(localDownloadPath, objectName).toString(); // 提交下载任务到线程池 Future<Void> future = executorService.submit(() -> { try { // 创建本地目录结构(如果对象表示一个目录,则直接创建目录) Path localDirPath = Paths.get(localPath).getParent(); if (localDirPath != null) { Files.createDirectories(localDirPath); } if (!item.isDir()) { Path localFilePath = Paths.get(localPath); try (InputStream objectInputStream = minioClient.getObject( GetObjectArgs.builder() .bucket(bucketName) .object(objectName) .build())) { Files.copy(objectInputStream, localFilePath, StandardCopyOption.REPLACE_EXISTING); System.out.println("Thread: " + Thread.currentThread().getName() + " - Successfully downloaded: " + objectName + " to " + localPath); } catch (NoSuchAlgorithmException | InvalidKeyException | IOException e) { System.err.println("Thread: " + Thread.currentThread().getName() + " - Failed to download " + objectName + " to " + localPath + ": " + e.getMessage()); // 可能需要删除或标记为无效的0字节文件,根据实际情况决定是否加入此逻辑 Files.deleteIfExists(localFilePath); } catch (MinioException me) { System.err.println("Thread: " + Thread.currentThread().getName() + " - Minio error occurred while downloading " + objectName + ": " + me.getMessage()); } } } catch (IOException e) { System.err.println("Thread: " + Thread.currentThread().getName() + " - Error creating directories for " + localPath + ": " + e.getMessage()); } return null; }); futures.add(future); } // 等待所有任务完成 for (Future<Void> future : futures) { future.get(); } System.out.println("All files have been downloaded successfully."); } catch (ExecutionException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { // 关闭线程池 executorService.shutdown(); } } }
//这里提醒一下,如果你是想数据迁移,请移步至我最近文章,这种方式不适合Minio升级或迁移