更新时间:2026-07-01 GMT+08:00
SDK是否支持批量上传、下载或复制对象?(Java SDK)
SDK暂未提供专门的批量上传、下载或复制对象接口,但您可以通过组合现有接口自行封装实现,请参考如下步骤操作:
- 列举出所有待上传、下载或者复制的对象。可参考列举对象章节,列举需上传、下载或复制的对象。
- 对列举出的对象调用单个对象的上传(上传对象)、下载(下载对象)或复制(复制对象)接口。
以批量上传对象为例,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | import com.obs.services.ObsClient; import com.obs.services.exception.ObsException; import com.obs.services.model.ObsObject; import java.io.ByteArrayInputStream; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class BatchUpload001 { private List<File> fileList = new ArrayList<>(); public static void main(String[] args) { // 您可以通过环境变量获取访问密钥AK/SK,也可以使用其他外部引入方式传入。如果使用硬编码可能会存在泄露风险。 // 您可以登录访问管理控制台获取访问密钥AK/SK String ak = System.getenv("ACCESS_KEY_ID"); String sk = System.getenv("SECRET_ACCESS_KEY_ID"); // 【可选】如果使用临时AK/SK和SecurityToken访问OBS,同样建议您尽量避免使用硬编码,以降低信息泄露风险。 // 您可以通过环境变量获取访问密钥AK/SK/SecurityToken,也可以使用其他外部引入方式传入。 // String securityToken = System.getenv("SECURITY_TOKEN"); // endpoint填写桶所在的endpoint, 此处以中国-香港为例,其他地区请按实际情况填写。 String endPoint = "https://obs.ap-southeast-1.myhuaweicloud.com"; // 您可以通过环境变量获取endPoint,也可以使用其他外部引入方式传入。 //String endPoint = System.getenv("ENDPOINT"); // 创建ObsClient实例 // 使用永久AK/SK初始化客户端 ObsClient obsClient = new ObsClient(ak, sk, endPoint); // 使用临时AK/SK和SecurityToken初始化客户端 // ObsClient obsClient = new ObsClient(ak, sk, securityToken, endPoint); try { String bucketName = "examplebucket"; // 定义桶内对象的前缀 String objectPre = "object/"; // 待上传的文件夹 String localDirPath = "localfile"; // 扫描文件夹下所有文件和空目录 File localDir = new File(localDirPath); if (!localDir.exists() || !localDir.isDirectory()) { System.out.println("本地文件夹不存在: " + localDirPath); return; } BatchUpload001 uploader = new BatchUpload001(); uploader.listFiles(localDir); if (uploader.fileList.isEmpty()) { System.out.println("未找到待上传的文件"); return; } System.out.println("待上传对象数量: " + uploader.fileList.size()); // 初始化线程池 int threadCount = 20; ExecutorService executorService = Executors.newFixedThreadPool(threadCount); CountDownLatch latch = new CountDownLatch(uploader.fileList.size()); AtomicInteger successCount = new AtomicInteger(0); AtomicInteger failCount = new AtomicInteger(0); // 执行并发上传 for (File f : uploader.fileList) { executorService.execute(() -> { try { String relativePath = f.getPath().substring(localDirPath.length() + 1); // 将Windows路径分隔符替换为OBS对象键的分隔符 String remoteObjectKey = objectPre + relativePath.replace("\\", "/"); if (f.isDirectory()) { // 如果是空文件夹,则在桶内创建对应的空文件夹对象 remoteObjectKey += "/"; obsClient.putObject(bucketName, remoteObjectKey, new ByteArrayInputStream(new byte[0])); } else { obsClient.putObject(bucketName, remoteObjectKey, f); } successCount.incrementAndGet(); System.out.println("上传成功: " + remoteObjectKey); } catch (ObsException e) { failCount.incrementAndGet(); System.out.println("上传失败: " + f.getPath() + ", HTTP Code: " + e.getResponseCode() + ", Error Code: " + e.getErrorCode() + ", Error Message: " + e.getErrorMessage()); } catch (Exception e) { failCount.incrementAndGet(); System.out.println("上传失败: " + f.getPath() + ", " + e.getMessage()); } finally { latch.countDown(); } }); } // 等待上传完成 executorService.shutdown(); latch.await(30, TimeUnit.MINUTES); System.out.println("上传完成, 成功: " + successCount.get() + ", 失败: " + failCount.get()); } catch (ObsException e) { System.out.println("创建ObsClient失败"); System.out.println("HTTP Code: " + e.getResponseCode()); System.out.println("Error Code: " + e.getErrorCode()); System.out.println("Error Message: " + e.getErrorMessage()); } catch (Exception e) { System.out.println("上传异常: " + e.getMessage()); e.printStackTrace(); } } // 递归扫描文件夹下所有文件和空目录 private void listFiles(File file) { File[] children = file.listFiles(); if (children == null) { return; } if (children.length == 0) { // 空文件夹也需要上传,将其添加到列表中 fileList.add(file); return; } for (File f : children) { if (f.isDirectory()) { listFiles(f); } else if (f.isFile()) { fileList.add(f); } } } } |
您可以使用多线程并发执行上传/下载/复制操作,以提高效率。
父主题: 常见问题(Java SDK)