文档首页/ 对象存储服务 OBS/ SDK参考/ Android/ 常见问题/ SDK如何进行批量操作?
更新时间:2026-09-10 GMT+08:00
分享

SDK如何进行批量操作?

目前SDK暂未提供此类接口,您需要自己封装批量上传、下载、复制或恢复对象的业务代码。步骤如下:

  1. 调用listObjects列举所有待下载、复制或恢复的对象,具体代码示例请参见列举对象,批量上传需要遍历本地待上传文件。
  2. 对列举出的对象调用单个对象的上传(上传对象)、下载(下载对象)、复制(复制对象)或恢复(恢复归档对象)接口。

您可以使用多线程并发执行上传/下载/复制/恢复操作,以提高效率。

代码示例一:批量上传

以下代码展示了批量上传对象。

import android.util.Log;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.PutObjectResult;
import java.io.File;

public class PutObjectDemo {
    private static final String TAG = "PutObjectDemo";

    public void execute() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量ACCESS_KEY_ID和SECRET_ACCESS_KEY_ID。
                // 您可以登录访问管理控制台获取访问密钥AK/SK
                String ak = System.getenv("ACCESS_KEY_ID");
                String sk = System.getenv("SECRET_ACCESS_KEY_ID");
                // endpoint填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。
                String endPoint = "https://your-endpoint";

                // 创建ObsClient实例
                ObsClient obsClient = new ObsClient(ak, sk, endPoint);
                try {
                    String bucketName = "examplebucket";
                    // 定义桶内对象的前缀
                    String objectPre = "object/";
                    // 待上传的文件夹
                    // Android 10及以上建议使用 context.getExternalFilesDir(null) 获取应用专属外部存储目录
                    // 此处使用硬编码路径仅作示例,实际使用时请替换为应用可访问的路径
                    String localDirPath = "/sdcard/Download/localDirPath";

                    // 遍历本地文件夹,逐个上传文件
                    File localDir = new File(localDirPath);
                    if (localDir != null && localDir.isDirectory()) {
                        File[] files = localDir.listFiles();
                        if (files != null) {
                            int succeedCount = 0;
                            int failCount = 0;
                            for (File file : files) {
                                if (file.isFile()) {
                                    try {
                                        String objectKey = objectPre + file.getName();
                                        PutObjectResult result = obsClient.putObject(bucketName, objectKey, file);
                                        Log.i(TAG, "Upload succeeded: " + objectKey);
                                        succeedCount++;
                                    } catch (Exception e) {
                                        Log.e(TAG, "batch upload failed: " + e.getMessage());
                                        failCount++;
                                    }
                                }
                            }
                            Log.i(TAG, "Batch upload completed. Succeed: " + succeedCount + ", Failed: " + failCount);
                        }
                    }
                } catch (ObsException e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, "HTTP Code:" + e.getResponseCode());
                    Log.e(TAG, "Error Code:" + e.getErrorCode());
                    Log.e(TAG, "Error Message:" + e.getErrorMessage());
                    Log.e(TAG, "Request ID:" + e.getErrorRequestId());
                    Log.e(TAG, "Host ID:" + e.getErrorHostId());
                } catch (Exception e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, e.getMessage());
                } finally {
                    try {
                        obsClient.close();
                    } catch (Exception e) {
                        // 忽略关闭异常
                    }
                }
            }
        }).start();
    }
}
  • 如果本地文件数量较多或文件较大,建议使用多线程并发执行上传操作,以提高效率。
  • 如需上传子文件夹中的文件,需递归遍历目录结构。
  • 如果待上传文件较大,可以使用断点续传上传接口(uploadFile)替换上传对象接口(putObject)。

代码示例二:批量下载

以下代码展示了批量下载对象。

import java.io.File;
import android.util.Log;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.ListObjectsRequest;
import com.obs.services.model.ObjectListing;
import com.obs.services.model.ObsObject;
import com.obs.services.model.DownloadFileRequest;

public class ListObjectsDemo {
    private static final String TAG = "ListObjectsDemo";

    public void execute() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量ACCESS_KEY_ID和SECRET_ACCESS_KEY_ID。
                // 您可以登录访问管理控制台获取访问密钥AK/SK
                String ak = System.getenv("ACCESS_KEY_ID");
                String sk = System.getenv("SECRET_ACCESS_KEY_ID");
                // endpoint填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。
                String endPoint = "https://your-endpoint";

                // 创建ObsClient实例
                ObsClient obsClient = new ObsClient(ak, sk, endPoint);
                try {
                    String bucketName = "examplebucket";
                    String objectPre = "object/";
                    // 本地下载目录
                    // Android 10及以上建议使用 context.getExternalFilesDir(null) 获取应用专属外部存储目录
                    // 此处使用硬编码路径仅作示例,实际使用时请替换为应用可访问的路径
                    String localDownloadDir = "/sdcard/Download/download";

                    // 1. 列举桶内指定前缀的所有对象
                    ListObjectsRequest listRequest = new ListObjectsRequest(bucketName);
                    listRequest.setPrefix(objectPre);
                    ObjectListing result = obsClient.listObjects(listRequest);

                    // 2. 逐个下载对象
                    for (ObsObject obsObject : result.getObjects()) {
                        String objectKey = obsObject.getObjectKey();
                        // 跳过文件夹对象(以"/"结尾的对象)
                        if (objectKey.endsWith("/")) {
                            continue;
                        }
                        // 生成本地文件路径
                        String localFilePath = localDownloadDir + "/" + objectKey.substring(objectPre.length());
                        // 确保本地目录存在,避免因目录不存在导致下载失败
                        File localFile = new File(localFilePath);
                        File parentDir = localFile.getParentFile();
                        if (parentDir != null && !parentDir.exists()) {
                            parentDir.mkdirs();
                        }
                        DownloadFileRequest downloadRequest = new DownloadFileRequest(bucketName, objectKey);
                        downloadRequest.setDownloadFile(localFilePath);
                        obsClient.downloadFile(downloadRequest);
                        Log.i(TAG, "Downloaded: " + objectKey);
                    }
                    Log.i(TAG, "Batch download completed");
                } catch (ObsException e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, "HTTP Code:" + e.getResponseCode());
                    Log.e(TAG, "Error Code:" + e.getErrorCode());
                    Log.e(TAG, "Error Message:" + e.getErrorMessage());
                    Log.e(TAG, "Request ID:" + e.getErrorRequestId());
                    Log.e(TAG, "Host ID:" + e.getErrorHostId());
                } catch (Exception e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, e.getMessage());
                } finally {
                    try {
                        obsClient.close();
                    } catch (Exception e) {
                        // 忽略关闭异常
                    }
                }
            }
        }).start();
    }
}
  • 您可以使用多线程并发执行下载操作,以提高效率。
  • 如果桶内对象数量较多,需要使用分页列举的方式获取全部对象,具体请参见 列举对象章节。

代码示例三:批量复制

以下代码展示了批量复制对象。

import android.util.Log;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.ListObjectsRequest;
import com.obs.services.model.ObjectListing;
import com.obs.services.model.ObsObject;
import com.obs.services.model.CopyObjectRequest;

public class ListObjectsDemo {
    private static final String TAG = "ListObjectsDemo";

    public void execute() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量ACCESS_KEY_ID和SECRET_ACCESS_KEY_ID。
                // 您可以登录访问管理控制台获取访问密钥AK/SK
                String ak = System.getenv("ACCESS_KEY_ID");
                String sk = System.getenv("SECRET_ACCESS_KEY_ID");
                // endpoint填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。
                String endPoint = "https://your-endpoint";

                // 创建ObsClient实例
                ObsClient obsClient = new ObsClient(ak, sk, endPoint);
                try {
                    String sourceBucketName = "examplebucket";
                    String destBucketName = "destbucket";
                    String objectPre = "object/";

                    // 1. 列举源桶内指定前缀的所有对象
                    ListObjectsRequest listRequest = new ListObjectsRequest(sourceBucketName);
                    listRequest.setPrefix(objectPre);
                    ObjectListing result = obsClient.listObjects(listRequest);

                    // 2. 逐个复制对象
                    for (ObsObject obsObject : result.getObjects()) {
                        String objectKey = obsObject.getObjectKey();
                        // 跳过文件夹对象
                        if (objectKey.endsWith("/")) {
                            continue;
                        }
                        CopyObjectRequest copyRequest = new CopyObjectRequest(sourceBucketName, objectKey, destBucketName, objectKey);
                        obsClient.copyObject(copyRequest);
                        Log.i(TAG, "Copied: " + objectKey);
                    }
                    Log.i(TAG, "Batch copy completed");
                } catch (ObsException e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, "HTTP Code:" + e.getResponseCode());
                    Log.e(TAG, "Error Code:" + e.getErrorCode());
                    Log.e(TAG, "Error Message:" + e.getErrorMessage());
                    Log.e(TAG, "Request ID:" + e.getErrorRequestId());
                    Log.e(TAG, "Host ID:" + e.getErrorHostId());
                } catch (Exception e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, e.getMessage());
                } finally {
                    try {
                        obsClient.close();
                    } catch (Exception e) {
                        // 忽略关闭异常
                    }
                }
            }
        }).start();
    }
}
  • 如果桶内对象数量较多,需要使用分页列举的方式获取全部对象,具体请参见 列举对象章节。

代码示例四:批量恢复

以下代码展示了按前缀批量恢复对象。

import android.util.Log;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.ListObjectsRequest;
import com.obs.services.model.ObjectListing;
import com.obs.services.model.ObsObject;
import com.obs.services.model.RestoreObjectRequest;
import com.obs.services.model.RestoreTierEnum;

public class ListObjectsDemo {
    private static final String TAG = "ListObjectsDemo";

    public void execute() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量ACCESS_KEY_ID和SECRET_ACCESS_KEY_ID。
                // 您可以登录访问管理控制台获取访问密钥AK/SK
                String ak = System.getenv("ACCESS_KEY_ID");
                String sk = System.getenv("SECRET_ACCESS_KEY_ID");
                // endpoint填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。
                String endPoint = "https://your-endpoint";

                // 创建ObsClient实例
                ObsClient obsClient = new ObsClient(ak, sk, endPoint);
                try {
                    String bucketName = "examplebucket";
                    String objectPre = "object/";

                    // 1. 列举桶内指定前缀的所有对象
                    ListObjectsRequest listRequest = new ListObjectsRequest(bucketName);
                    listRequest.setPrefix(objectPre);
                    ObjectListing listing = obsClient.listObjects(listRequest);

                    // 2. 逐个恢复归档或深度归档存储对象
                    int succeedCount = 0;
                    int failCount = 0;
                    for (ObsObject obsObject : listing.getObjects()) {
                        String objectKey = obsObject.getObjectKey();
                        // 跳过文件夹对象(以"/"结尾的对象)
                        if (objectKey.endsWith("/")) {
                            continue;
                        }
                        try {
                            RestoreObjectRequest request = new RestoreObjectRequest();
                            request.setBucketName(bucketName);
                            request.setObjectKey(objectKey);
                            // 设置恢复对象的保存天数
                            request.setRestoreDays(7);
                            // 设置恢复选项为标准恢复
                            request.setTier(RestoreTierEnum.STANDARD);

                            obsClient.restoreObject(request);
                            Log.i(TAG, "Restore succeeded: " + objectKey);
                            succeedCount++;
                        } catch (Exception e) {
                            Log.e(TAG, "batch restore failed: " + e.getMessage());
                            failCount++;
                        }
                    }
                    Log.i(TAG, "Batch restore completed. Succeed: " + succeedCount + ", Failed: " + failCount);
                } catch (ObsException e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, "HTTP Code:" + e.getResponseCode());
                    Log.e(TAG, "Error Code:" + e.getErrorCode());
                    Log.e(TAG, "Error Message:" + e.getErrorMessage());
                    Log.e(TAG, "Request ID:" + e.getErrorRequestId());
                    Log.e(TAG, "Host ID:" + e.getErrorHostId());
                } catch (Exception e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, e.getMessage());
                } finally {
                    try {
                        obsClient.close();
                    } catch (Exception e) {
                        // 忽略关闭异常
                    }
                }
            }
        }).start();
    }
}

以下代码展示了按对象名列表批量恢复对象。

import android.util.Log;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.RestoreObjectRequest;
import com.obs.services.model.RestoreTierEnum;

public class RestoreObjectDemo {
    private static final String TAG = "RestoreObjectDemo";

    public void execute() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量ACCESS_KEY_ID和SECRET_ACCESS_KEY_ID。
                // 您可以登录访问管理控制台获取访问密钥AK/SK
                String ak = System.getenv("ACCESS_KEY_ID");
                String sk = System.getenv("SECRET_ACCESS_KEY_ID");
                // endpoint填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。
                String endPoint = "https://your-endpoint";

                // 创建ObsClient实例
                ObsClient obsClient = new ObsClient(ak, sk, endPoint);
                try {
                    String bucketName = "examplebucket";
                    // 待恢复的对象名列表
                    String[] objectKeys = {"objectname1", "objectname2", "objectname3"};

                    int succeedCount = 0;
                    int failCount = 0;
                    for (String objectKey : objectKeys) {
                        try {
                            RestoreObjectRequest request = new RestoreObjectRequest();
                            request.setBucketName(bucketName);
                            request.setObjectKey(objectKey);
                            // 设置恢复对象的保存天数
                            request.setRestoreDays(1);
                            // 设置恢复选项为快速恢复
                            request.setTier(RestoreTierEnum.EXPEDITED);

                            obsClient.restoreObject(request);
                            Log.i(TAG, "Restore succeeded: " + objectKey);
                            succeedCount++;
                        } catch (Exception e) {
                            Log.e(TAG, "batch restore failed: " + e.getMessage());
                            failCount++;
                        }
                    }
                    Log.i(TAG, "Batch restore completed. Succeed: " + succeedCount + ", Failed: " + failCount);
                } catch (ObsException e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, "HTTP Code:" + e.getResponseCode());
                    Log.e(TAG, "Error Code:" + e.getErrorCode());
                    Log.e(TAG, "Error Message:" + e.getErrorMessage());
                    Log.e(TAG, "Request ID:" + e.getErrorRequestId());
                    Log.e(TAG, "Host ID:" + e.getErrorHostId());
                } catch (Exception e) {
                    Log.e(TAG, "execute failed");
                    Log.e(TAG, e.getMessage());
                } finally {
                    try {
                        obsClient.close();
                    } catch (Exception e) {
                        // 忽略关闭异常
                    }
                }
            }
        }).start();
    }
}
  • 如果桶内对象数量较多,需要使用分页列举的方式获取全部对象,具体请参见 列举对象章节。

相关文档