Object Storage Service (OSS) は、マルチパートアップロード機能を提供します。この機能を使用すると、大きいオブジェクトを複数のパートに分割し、各パートを個別にアップロードできます。アップロードが完了したら、CompleteMultipartUpload 操作を呼び出して、これらのパートを完全なオブジェクトに結合できます。
注意事項
このトピックのサンプルコードを実行する前に、カスタムドメイン名や Security Token Service (STS) を使用するなどの方法で OSSClient インスタンスを作成する必要があります。詳細については、「初期化」をご参照ください。
説明OSSClient インスタンスを初期化する際に、バケットが配置されているリージョンに対応するエンドポイントを指定します。
ファイルをアップロードするには、
oss:PutObject権限が必要です。詳細については、「RAM ユーザーへのカスタムポリシーのアタッチ」をご参照ください。
マルチパートアップロードのプロセス
マルチパートアップロードを実行するには、次の手順を実行します。
アップロードするオブジェクトをパートに分割します。
InitiateMultipartUpload 操作を呼び出して、マルチパートアップロードタスクを開始します。
UploadPart 操作を呼び出して、パートを 1 つずつ、または並行してアップロードします。
CompleteMultipartUpload 操作を呼び出して、アップロードタスクを完了します。
この手順に関する注意事項は次のとおりです。
最後のパートを除き、各パートのサイズは 100 KB 以上である必要があります。そうでない場合、CompleteMultipartUpload 操作は失敗します。
オブジェクト内でのパートの位置は、アップロードプロセス中に指定するパート番号によって決まります。パートは順番にアップロードする必要はなく、同時にアップロードすることも可能です。
パートを同時にアップロードするには、ご利用のネットワーク状況とデバイスの負荷に基づいて、適切な同時実行レベルを指定する必要があります。同時実行レベルが高いほどアップロード速度が速くなるとは限りません。ネットワーク状況が安定している場合はパートサイズを大きくし、不安定な場合はパートサイズを小さくすることを推奨します。
デフォルトでは、オブジェクトのパートをアップロードしても CompleteMultipartUpload 操作を呼び出してこれらのパートを結合しない場合、アップロードされたパートは自動的に削除されません。AbortMultipartUpload 操作を呼び出して、アップロードタスクを終了し、パートを削除できます。アップロードされたパートを自動的に削除する方法の詳細については、「最終更新時間に基づくライフサイクルルール」をご参照ください。
マルチパートアップロードタスクの完全なサンプルコード
以下に、マルチパートアップロードタスクを実装する完全なサンプルコードを示します。
__block NSString * uploadId = nil;
__block NSMutableArray * partInfos = [NSMutableArray new];
// バケット名を指定します。例:examplebucket。
NSString * uploadToBucket = @"examplebucket";
// オブジェクトのフルパスを指定します。例:exampledir/exampleobject.txt。フルパスにバケット名を含めないでください。
NSString * uploadObjectkey = @"exampledir/exampleobject.txt";
// OSSInitMultipartUploadRequest を使用して、アップロードされたオブジェクトの名前と、オブジェクトが格納されているバケットの名前を指定します。
OSSInitMultipartUploadRequest * init = [OSSInitMultipartUploadRequest new];
init.bucketName = uploadToBucket;
init.objectKey = uploadObjectkey;
// init.contentType = @"application/octet-stream";
// multipartUploadInit への応答には、アップロード ID が含まれます。アップロード ID は、マルチパートアップロードタスクの一意の ID です。
OSSTask * initTask = [client multipartUploadInit:init];
[initTask waitUntilFinished];
if (!initTask.error) {
OSSInitMultipartUploadResult * result = initTask.result;
uploadId = result.uploadId;
// アップロード ID に基づいて、マルチパートアップロードタスクをキャンセルするか、アップロードされたパートをリスト表示します。
// アップロード ID に基づいてマルチパートアップロードタスクをキャンセルする場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後にアップロード ID を取得します。
// アップロード ID に基づいてマルチパートアップロードタスク内のアップロード済みパートをリスト表示する場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後、CompleteMultipartUpload 操作を呼び出してマルチパートアップロードタスクを完了する前にアップロード ID を取得します。
//NSLog(@"UploadId": %@, uploadId);
} else {
NSLog(@"multipart upload failed, error: %@", initTask.error);
return;
}
// アップロードするオブジェクトを指定します。
NSString * filePath = @"<filepath>";
// オブジェクトのサイズを照会します。
uint64_t fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil] fileSize];
// パート数を指定します。
int chuckCount = 10;
// パートサイズを指定します。
uint64_t offset = fileSize/chuckCount;
for (int i = 1; i <= chuckCount; i++) {
OSSUploadPartRequest * uploadPart = [OSSUploadPartRequest new];
uploadPart.bucketName = uploadToBucket;
uploadPart.objectkey = uploadObjectkey;
uploadPart.uploadId = uploadId;
uploadPart.partNumber = i; // パート番号は 1 から始まります
NSFileHandle* readHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
[readHandle seekToFileOffset:offset * (i -1)];
NSData* data = [readHandle readDataOfLength:offset];
uploadPart.uploadPartData = data;
OSSTask * uploadPartTask = [client uploadPart:uploadPart];
[uploadPartTask waitUntilFinished];
if (!uploadPartTask.error) {
OSSUploadPartResult * result = uploadPartTask.result;
uint64_t fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:uploadPart.uploadPartFileURL.absoluteString error:nil] fileSize];
[partInfos addObject:[OSSPartInfo partInfoWithPartNum:i eTag:result.eTag size:fileSize]];
} else {
NSLog(@"upload part error: %@", uploadPartTask.error);
return;
}
}
OSSCompleteMultipartUploadRequest * complete = [OSSCompleteMultipartUploadRequest new];
complete.bucketName = uploadToBucket;
complete.objectKey = uploadObjectkey;
complete.uploadId = uploadId;
complete.partInfos = partInfos;
OSSTask * completeTask = [client completeMultipartUpload:complete];
[[completeTask continueWithBlock:^id(OSSTask *task) {
if (!task.error) {
OSSCompleteMultipartUploadResult * result = task.result;
// ...
} else {
// ...
}
return nil;
}] waitUntilFinished];マルチパートアップロードを使用したローカルファイルのアップロード
上記の完全なサンプルコードは、マルチパートアップロードのプロセスに従ってマルチパートアップロードタスクを実装します。次のサンプルコードは、上記の完全なサンプルコードをカプセル化し、MultipartUploadRequest を使用するだけでローカルファイルをパートに分けてアップロードできるようにします。
以下に、マルチパートアップロードを使用してローカルファイルをアップロードする方法の例を示します。
// バケット名を指定します。例:examplebucket。
NSString *bucketName = @"examplebucket";
// オブジェクトのフルパスを指定します。例:exampledir/exampleobject.txt。フルパスにバケット名を含めないでください。
NSString *objectKey = @"exampledir/exampleobject.txt";
OSSMultipartUploadRequest * multipartUploadRequest = [OSSMultipartUploadRequest new];
multipartUploadRequest.bucketName = bucketName;
multipartUploadRequest.objectKey = objectKey;
// パートサイズを指定します。デフォルトのパートサイズは 256 KB です。
multipartUploadRequest.partSize = 1024 * 1024;
multipartUploadRequest.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
NSLog(@"progress: %lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};
multipartUploadRequest.uploadingFileURL = [[NSBundle mainBundle] URLForResource:@"wangwang" withExtension:@"zip"];
OSSTask * multipartTask = [client multipartUpload:multipartUploadRequest];
[[multipartTask continueWithBlock:^id(OSSTask *task) {
if (task.error) {
NSLog(@"error: %@", task.error);
} else {
NSLog(@"Upload file success");
}
return nil;
}] waitUntilFinished];アップロード済みパートのリスト表示
listParts メソッドを呼び出して、特定のアップロードイベントでアップロードされたすべてのパートをリスト表示します。
OSSListPartsRequest * listParts = [OSSListPartsRequest new];
// バケット名を指定します。例:examplebucket。
listParts.bucketName = @"examplebucket";
// オブジェクトのフルパスを指定します。例:exampledir/exampleobject.txt。フルパスにバケット名を含めないでください。
listParts.objectKey = @"exampledir/exampleobject.txt";
// アップロード ID を指定します。InitiateMultipartUpload 操作の応答からアップロード ID を取得できます。CompleteMultipartUpload 操作を呼び出してマルチパートアップロードタスクを完了する前に、アップロード ID を取得する必要があります。
listParts.uploadId = @"0004B999EF518A1FE585B0C9****";
OSSTask * listPartTask = [client listParts:listParts];
[listPartTask continueWithBlock:^id(OSSTask *task) {
if (!task.error) {
NSLog(@"list part result success!");
OSSListPartsResult * listPartResult = task.result;
for (NSDictionary * partInfo in listPartResult.parts) {
NSLog(@"each part: %@", partInfo);
}
} else {
NSLog(@"list part result error: %@", task.error);
}
return nil;
}];
// waitUntilFinished は現在のスレッドの実行をブロックしますが、タスクの進行はブロックしません。
// [listPartTask waitUntilFinished]; デフォルトでは、バケットにマルチパートアップロードでアップロードされたパートが 1,000 個を超える場合、OSS は最初の 1,000 個のパートを返します。応答では、IsTruncated フィールドの値が `true` になり、次のリスト操作の開始位置を示す `NextPartNumberMarker` が返されます。
マルチパートアップロードタスクのキャンセル
以下のコードは、特定の UploadId に対するマルチパートアップロードリクエストをキャンセルします。
OSSAbortMultipartUploadRequest * abort = [OSSAbortMultipartUploadRequest new];
// バケット名を指定します。例:examplebucket。
abort.bucketName = @"examplebucket";
// オブジェクトのフルパスを指定します。例:exampledir/exampleobject.txt。フルパスにバケット名を含めないでください。
abort.objectKey = @"exampledir/exampleobject.txt";
// アップロード ID を指定します。InitiateMultipartUpload 操作の応答からアップロード ID を取得できます。
abort.uploadId = @"0004B999EF518A1FE585B0C9****";
OSSTask * abortTask = [client abortMultipartUpload:abort];
[abortTask waitUntilFinished];
if (!abortTask.error) {
OSSAbortMultipartUploadResult * result = abortTask.result;
uploadId = result.uploadId;
} else {
NSLog(@"multipart upload failed, error: %@", abortTask.error);
return;
}
// waitUntilFinished は現在のスレッドの実行をブロックしますが、タスクの進行はブロックしません。
// [abortTask waitUntilFinished]; 関連ドキュメント
マルチパートアップロードを実行するために使用される完全なサンプルコードについては、GitHub をご参照ください。
マルチパートアップロードには 3 つの API 操作が含まれます。これらの操作の詳細については、次のトピックをご参照ください。
アップロードされたパートをリスト表示するために呼び出すことができる API 操作の詳細については、「ListParts」をご参照ください。
マルチパートアップロードタスクをキャンセルするために呼び出すことができる API 操作の詳細については、「AbortMultipartUpload」をご参照ください。