Object Storage Service (OSS) は、マルチパートアップロード機能を提供します。この機能を使用すると、大きなオブジェクトを複数のパートに分割して、それぞれを個別にアップロードできます。すべてのパートがアップロードされた後、CompleteMultipartUpload 操作を呼び出して、パートを完全なオブジェクトに結合できます。このプロセスにより、再開可能なアップロードが可能になります。
注意事項
このトピックのサンプルコードを実行する前に、カスタムドメイン名やセキュリティトークンサービス (STS) を使用するなどの方法で OSSClient インスタンスを作成する必要があります。詳細については、「初期化 (Android SDK)」をご参照ください。
マルチパートアップロードのプロセス
マルチパートアップロードは、次の 3 つのステップで構成されます。
マルチパートアップロードイベントを開始します。
oss.initMultipartUpload メソッドを呼び出します。OSS は、グローバルに一意の uploadId を返します。
パートをアップロードします。
oss.uploadPart メソッドを呼び出して、各パートをアップロードします。
説明特定の uploadId に対して、パート番号は完全なオブジェクト内でのパートの位置を識別します。既存のパートと同じパート番号で新しいパートをアップロードすると、既存のパートは上書きされます。
OSS は、受信したパートデータの MD5 ハッシュを応答の ETag ヘッダーに含めます。
OSS は、アップロードされたデータの MD5 ハッシュを計算し、SDK によって計算された MD5 ハッシュと比較します。2 つのハッシュが一致しない場合、OSS は InvalidDigest エラーコードを返します。
マルチパートアップロードを完了します。
すべてのパートがアップロードされた後、oss.CompleteMultipartUpload メソッドを呼び出して、すべてのパートを完全なオブジェクトに結合します。
マルチパートアップロードの完全な例
次の例は、マルチパートアップロードの完全なプロセスを示しています。
// バケット名を指定します (例: examplebucket)。
String bucketName = "examplebucket";
// オブジェクトの完全なパスを指定します (例: exampledir/exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。
String objectName = "exampledir/exampleobject.txt";
// ローカルファイルの完全なパスを指定します (例: /storage/emulated/0/oss/examplefile.txt)。
String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
// マルチパートアップロードを初期化します。
InitiateMultipartUploadRequest init = new InitiateMultipartUploadRequest(bucketName, objectName);
InitiateMultipartUploadResult initResult = oss.initMultipartUpload(init);
// uploadId が返されます。
String uploadId = initResult.getUploadId();
// uploadId を使用して、マルチパートアップロードイベントをキャンセルしたり、アップロードされたパートをリスト表示したりします。
// uploadId に基づいてマルチパートアップロードイベントをキャンセルするには、InitiateMultipartUpload を呼び出してマルチパートアップロードを初期化した後に uploadId を取得します。
// uploadId に基づいてアップロードされたパートをリスト表示するには、InitiateMultipartUpload を呼び出してマルチパートアップロードを初期化し、CompleteMultipartUpload を呼び出してマルチパートアップロードを完了する前に uploadId を取得します。
// Log.d("uploadId", uploadId);
// 1 つのパートのサイズをバイト単位で設定します。パートの最小サイズは 100 KB、最大サイズは 5 GB です。最後のパートのサイズは 100 KB 未満でもかまいません。
int partCount = 100 * 1024;
// パートをアップロードします。
List<PartETag> partETags = new ArrayList<>();
for (int i = 1; i < 5; i++) {
byte[] data = new byte[partCount];
RandomAccessFile raf = new RandomAccessFile(localFilepath, "r");
long skip = (i-1) * partCount;
raf.seek(skip);
raf.readFully(data, 0, partCount);
UploadPartRequest uploadPart = new UploadPartRequest();
uploadPart.setBucketName(bucketName);
uploadPart.setObjectKey(objectName);
uploadPart.setUploadId(uploadId);
// パート番号を設定します。パート番号は 1 から始まります。アップロードされる各パートには、1 から 10,000 までのパート番号があります。
uploadPart.setPartNumber(i);
uploadPart.setPartContent(data);
try {
UploadPartResult result = oss.uploadPart(uploadPart);
PartETag partETag = new PartETag(uploadPart.getPartNumber(), result.getETag());
partETags.add(partETag);
} catch (ServiceException serviceException) {
OSSLog.logError(serviceException.getErrorCode());
}
}
Collections.sort(partETags, new Comparator<PartETag>() {
@Override
public int compare(PartETag lhs, PartETag rhs) {
if (lhs.getPartNumber() < rhs.getPartNumber()) {
return -1;
} else if (lhs.getPartNumber() > rhs.getPartNumber()) {
return 1;
} else {
return 0;
}
}
});
// マルチパートアップロードを完了します。
CompleteMultipartUploadRequest complete = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
// アップロードコールバック。マルチパートアップロードリクエストを完了するときに、CALLBACK_SERVER パラメーターを設定できます。リクエストが完了すると、指定されたサーバーアドレスにコールバックリクエストが送信されます。返された結果の completeResult.getServerCallbackReturnBody() からサーバーコールバックの結果を表示できます。
complete.setCallbackParam(new HashMap<String, String>() {
{
put("callbackUrl", CALLBACK_SERVER); // 値をご利用のサーバーアドレスに変更します。
put("callbackBody", "test");
}
});
CompleteMultipartUploadResult completeResult = oss.completeMultipartUpload(complete);
OSSLog.logError("-------------- serverCallback: " + completeResult.getServerCallbackReturnBody());上記のコードは、uploadPart を呼び出して各パートをアップロードします。
各パートのアップロードリクエストでは、uploadId と partNumber を指定する必要があります。partNumber の値は 1 から 10,000 の範囲内である必要があります。partNumber がこの範囲外の場合、OSS は InvalidArgument エラーコードを返します。
uploadPart を呼び出すとき、最後のパートを除くすべてのパートは 100 KB より大きい必要があります。OSS は、マルチパートアップロードを完了するときにのみパートサイズをチェックします。
各パートをアップロードする前に、ストリームをそのパートのデータの先頭に配置する必要があります。
各パートがアップロードされた後、OSS の応答にはそのパートの ETag 値が含まれます。ETag 値は、パートデータの MD5 ハッシュです。ETag 値とパート番号を組み合わせて PartETag を作成し、マルチパートアップロードを完了するために保存する必要があります。
ローカルファイルのマルチパートアップロード
同期または非同期のマルチパートアップロードを使用して、ローカルファイルを OSS にアップロードできます。
前のセクションでは、マルチパートアップロードのプロセスをステップバイステップで示す完全な例を提供しました。このセクションのローカルファイルをアップロードするためのコードは、そのプロセスをカプセル化したものです。MultipartUploadRequest を使用するだけで、マルチパートアップロードを実行できます。
同期マルチパートアップロード操作を使用したローカルファイルのアップロード
次のコードは、examplefile.txt ファイルを examplebucket バケットの exampledir フォルダーに同期的にアップロードし、exampleobject.txt オブジェクトとして保存する方法を示しています。
// バケット名を指定します (例: examplebucket)。 String bucketName = "examplebucket"; // オブジェクトの完全なパスを指定します (例: exampledir/exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。 String objectName = "exampledir/exampleobject.txt"; // ローカルファイルの完全なパスを指定します (例: /storage/emulated/0/oss/examplefile.txt)。 String localFilepath = "/storage/emulated/0/oss/examplefile.txt"; ObjectMetadata meta = new ObjectMetadata(); // ファイルのメタデータを設定します。 meta.setHeader("x-oss-object-acl", "public-read-write"); MultipartUploadRequest rq = new MultipartUploadRequest(bucketName, objectName, localFilepath, meta); // パートサイズを設定します。デフォルトのパートサイズは 256 KB です。最小パートサイズは 100 KB です。 rq.setPartSize(1024 * 1024); rq.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() { @Override public void onProgress(MultipartUploadRequest request, long currentSize, long totalSize) { OSSLog.logDebug("[testMultipartUpload] - " + currentSize + " " + totalSize, false); } }); CompleteMultipartUploadResult result = oss.multipartUpload(rq);Android 10 以降の対象範囲別ストレージの場合、ファイルの URI を使用してファイルを OSS にアップロードできます。
// バケット名を指定します (例: examplebucket)。 String bucketName = "examplebucket"; // オブジェクトの完全なパスを指定します (例: exampledir/exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。 String objectName = "exampledir/exampleobject.txt"; ObjectMetadata meta = new ObjectMetadata(); // ファイルのメタデータを設定します。 meta.setHeader("x-oss-object-acl", "public-read-write"); MultipartUploadRequest rq = new MultipartUploadRequest(bucketName, objectName, fileUri, meta); // パートサイズを設定します。デフォルトのパートサイズは 256 KB です。最小パートサイズは 100 KB です。 rq.setPartSize(1024 * 1024); rq.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() { @Override public void onProgress(MultipartUploadRequest request, long currentSize, long totalSize) { OSSLog.logDebug("[testMultipartUpload] - " + currentSize + " " + totalSize, false); } }); CompleteMultipartUploadResult result = oss.multipartUpload(rq);非同期 API を呼び出して実行するローカルファイルのマルチパートアップロード
次のコードは、examplefile.txt ファイルを examplebucket バケットの exampledir フォルダーに非同期的にアップロードし、exampleobject.txt オブジェクトとして保存する方法を示しています。
// バケット名を指定します (例: examplebucket)。 String bucketName = "examplebucket"; // オブジェクトの完全なパスを指定します (例: exampledir/exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。 String objectName = "exampledir/exampleobject.txt"; // ローカルファイルの完全なパスを指定します (例: /storage/emulated/0/oss/examplefile.txt)。 String localFilepath = "/storage/emulated/0/oss/examplefile.txt"; MultipartUploadRequest request = new MultipartUploadRequest(bucketName, objectName, localFilepath); request.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() { @Override public void onProgress(MultipartUploadRequest request, long currentSize, long totalSize) { OSSLog.logDebug("[testMultipartUpload] - " + currentSize + " " + totalSize, false); } }); OSSAsyncTask task = oss.asyncMultipartUpload(request, new OSSCompletedCallback<MultipartUploadRequest, CompleteMultipartUploadResult>() { @Override public void onSuccess(MultipartUploadRequest request, CompleteMultipartUploadResult result) { OSSLog.logInfo(result.getServerCallbackReturnBody()); } @Override public void onFailure(MultipartUploadRequest request, ClientException clientException, ServiceException serviceException) { OSSLog.logError(serviceException.getRawMessage()); } }); //Thread.sleep(100); // マルチパートアップロードをキャンセルします。 //task.cancel(); task.waitUntilFinished();Android 10 以降の対象範囲別ストレージの場合、ファイルの URI を使用してファイルを OSS にアップロードできます。
// バケット名を指定します (例: examplebucket)。 String bucketName = "examplebucket"; // オブジェクトの完全なパスを指定します (例: exampledir/exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。 String objectName = "exampledir/exampleobject.txt"; MultipartUploadRequest request = new MultipartUploadRequest(bucketName, objectName, fileUri); request.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() { @Override public void onProgress(MultipartUploadRequest request, long currentSize, long totalSize) { OSSLog.logDebug("[testMultipartUpload] - " + currentSize + " " + totalSize, false); } }); OSSAsyncTask task = oss.asyncMultipartUpload(request, new OSSCompletedCallback<MultipartUploadRequest, CompleteMultipartUploadResult>() { @Override public void onSuccess(MultipartUploadRequest request, CompleteMultipartUploadResult result) { OSSLog.logInfo(result.getServerCallbackReturnBody()); } @Override public void onFailure(MultipartUploadRequest request, ClientException clientException, ServiceException serviceException) { OSSLog.logError(serviceException.getRawMessage()); } }); //Thread.sleep(100); // マルチパートアップロードをキャンセルします。 //task.cancel(); task.waitUntilFinished();
アップロード済みパートのリスト表示
oss.listParts メソッドを呼び出して、特定のマルチパートアップロードイベントでアップロードされたすべてのパートを取得します。
次のコードは、アップロードされたパートをリスト表示する方法を示しています。
// バケット名を指定します (例: examplebucket)。
String bucketName = "examplebucket";
// オブジェクトの完全なパスを指定します (例: exampledir/exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。
String objectName = "exampledir/exampleobject.txt";
// uploadId を指定します。uploadId は、InitiateMultipartUpload を呼び出してマルチパートアップロードを初期化し、CompleteMultipartUpload を呼び出してマルチパートアップロードを完了する前に、応答から取得します。
String uploadId = "0004B999EF518A1FE585B0C9****";
// パートをリスト表示します。
ListPartsRequest listParts = new ListPartsRequest(bucketName, objectName, uploadId);
ListPartsResult result = oss.listParts(listParts);
List<PartETag> partETagList = new ArrayList<PartETag>();
for (PartSummary part : result.getParts()) {
partETagList.add(new PartETag(part.getPartNumber(), part.getETag()));
}デフォルトでは、バケットにマルチパートアップロードを使用してアップロードされたパートが 1,000 個以上含まれている場合、OSS は最初の 1,000 パートを返します。応答では、IsTruncated フィールドの値は true になり、NextPartNumberMarker が返されて次のリスト操作の開始位置を示します。
マルチパートアップロードイベントのキャンセル
oss.abortMultipartUpload メソッドを呼び出して、マルチパートアップロードイベントをキャンセルします。マルチパートアップロードイベントがキャンセルされると、その uploadId をどの操作にも使用できなくなります。アップロードされたパートは削除されます。
次のコードは、マルチパートアップロードイベントをキャンセルする方法を示しています。
// バケット名を指定します (例: examplebucket)。
String bucketName = "examplebucket";
// オブジェクトの完全なパスを指定します (例: exampledir/exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。
String objectName = "exampledir/exampleobject.txt";
// uploadId を指定します。uploadId は、InitiateMultipartUpload を呼び出してマルチパートアップロードを初期化した後に応答から取得します。
String uploadId = "0004B999EF518A1FE585B0C9****";
// マルチパートアップロードをキャンセルします。
AbortMultipartUploadRequest abort = new AbortMultipartUploadRequest(bucketName, objectName, uploadId);
AbortMultipartUploadResult abortResult = oss.abortMultipartUpload(abort);関連ドキュメント
マルチパートアップロードの完全なサンプルコードについては、GitHub をご参照ください。
マルチパートアップロードには 3 つの API 操作が含まれます。操作の詳細については、次のトピックをご参照ください。
マルチパートアップロードイベントをキャンセルするために使用される API 操作の詳細については、「AbortMultipartUpload」をご参照ください。
アップロードされたパートをリスト表示するために使用される API 操作の詳細については、「ListParts」をご参照ください。
進行中のすべてのマルチパートアップロードイベント (開始されたがまだ完了またはキャンセルされていないイベント) をリスト表示するために使用される API 操作の詳細については、「ListMultipartUploads」をご参照ください。
OSSClient インスタンスを初期化する方法の詳細については、「Android 用の OSSClient インスタンスの初期化」をご参照ください。