edit-icon download-icon

MultipartUpload

最終更新日: Sep 14, 2016

OSS では、putObject インターフェイスを使用した OSS へのファイルのアップロードに加えて、マルチパートアップロードモードが提供されます。マルチパートアップロードモードを適用できるシナリオの一部の例を次に示します。

  • ブレークポイントアップロードが必要な場合
  • 100 MB を超えるオブジェクトをアップロードする場合
  • ネットワークの条件が悪く、OSS サーバーとの接続が頻繁に切断される場合
  • ファイルをアップロードする前に、そのサイズを特定できない場合

ここでは、マルチパートアップロードの手順の概要について説明します。

マルチパートアップロードの手順

マルチパートアップロードの初期化

次のように initiateMultipartUpload メソッドを使用して、マルチパートアップロードタスクを初期化します。

  1. String bucketName = "your-bucket-name";
  2. String key = "your-key";
  3. // Initialize OSSClient
  4. var client = new OssClient(endpoint, accessId, accessKey);
  5. // Starts Multipart Upload
  6. var request = new InitiateMultipartUploadRequest(bucketName, objectName);
  7. var result = client.InitiateMultipartUpload(request);
  8. // Prints UploadId
  9. Console.WriteLine(result.UploadId);

InitiateMultipartUploadRequest を使用してアップロードするオブジェクトの名前とバケットを指定します。InitiateMultipartUploadRequest では、ObjectMetadata も設定することができますが、ContentLength を指定する必要はありません。initiateMultipartUpload から返される結果には UploadId が含まれます。これは、マルチパートアップロードタスクの一意の ID です。後の操作でこれを使用します。

次に、パートをアップロードするための 2 つのメソッドを使用します。ローカルディスクからアップロードする場合は Upload Part を使用し、バケットからオブジェクトのコピーを取得するには Upload Part Copy を使用します。

Upload Part ローカルのアップロード

次に、パート単位でローカルファイルをアップロードします。パス /path/to/file.zip に 1 つのファイルがあるとします。このファイルは大きいので、OSS にマルチパートアップロードする必要があります。

  1. // Initialize OSSClient
  2. var client = new OssClient(endpoint, accessId, accessKey);
  3. var fi = new FileInfo(fileToUpload);
  4. var fileSize = fi.Length;
  5. var partCount = fileSize / partSize;
  6. if (fileSize % partSize != 0)
  7. {
  8. partCount++;
  9. }
  10. var partETags = new List<PartETag>();
  11. for (var i = 0; i < partCount; i++)
  12. {
  13. using (var fs = File.Open(fileToUpload, FileMode.Open))
  14. {
  15. var skipBytes = (long)partSize * i;
  16. fs.Seek(skipBytes, 0);
  17. var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
  18. var request = new UploadPartRequest(bucketName, objectName, uploadId)
  19. {
  20. InputStream = fs,
  21. PartSize = size,
  22. PartNumber = i + 1
  23. };
  24. var result = _ossClient.UploadPart(request);
  25. partETags.Add(result.PartETag);
  26. }
  27. }

このプログラムの主な目的は、uploadPart メソッドを呼び出して各パートをアップロードすることです。ただし、次の点に注意する必要があります。

  • uploadPart メソッドでは、最後のパートを除くすべてのパートは 100 KB を超えている必要があります。ただし、Upload Part インターフェイスでは、アップロードされたパートのサイズがすぐに検証されるわけではありません (そのパートが最後のパートかどうかがわからないため)。アップロードされたパートのサイズは、マルチパートアップロードが完了して初めて検証されます。
  • OSS は、サーバーから受信したデータパートの MD5 値を ETag ヘッダーに配置し、それをユーザーに返します。
  • ネットワーク経由で転送されたデータにエラーがないことを確認するために、ContentMD5 を設定できます。OSS ではアップロードされたデータの MD5 値が計算され、ユーザーがアップロードした MD5 値と比較されます。それらの値が一致しない場合、InvalidDigest エラーコードが返されます。
  • パート番号の範囲は 1 ~ 10000 です。この範囲を超えている場合、OSS は InvalidArgument エラーコードを返します。
  • 各パートは、アップロードされるとき、次のパートの開始に対応する場所へのストリームを取得します。
  • 各パートがアップロードされた後、OSS から返される結果には PartETag オブジェクトが含まれます。これは、アップロードするパートの ETag と PartNumber の組み合わせです。これを以降の手順で使用するため、保存する必要があります。通常はこれらの PartETag オブジェクトをリストに保存します。

Upload Part Copy

Upload Part Copy を使用し、既存のオブジェクトからデータをコピーしてオブジェクトをアップロードします。500 MB を超えるオブジェクトをコピーするときは、Upload Part Copy メソッドを使用することをお勧めします。

  1. // Initialize OSSClient
  2. var client = new OssClient(endpoint, accessId, accessKey);
  3. var metadata = client.GetObjectMetadata(sourceBucket, sourceObject);
  4. var fileSize = metadata.ContentLength;
  5. var partCount = (int)fileSize / partSize;
  6. if (fileSize % partSize != 0)
  7. {
  8. partCount++;
  9. }
  10. var partETags = new List<PartETag>();
  11. for (var i = 0; i < partCount; i++)
  12. {
  13. var skipBytes = (long)partSize * i;
  14. var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
  15. var request = new UploadPartCopyRequest(targetBucket, targetObject, sourceBucket, sourceObject, uploadId)
  16. {
  17. PartSize = size,
  18. PartNumber = i + 1,
  19. BeginIndex = skipBytes
  20. };
  21. var result = client.UploadPartCopy(request);
  22. partETags.Add(result.PartETag);
  23. }

上記のプログラムでは、uploadPartCopy メソッドが呼び出されて各パートがコピーされます。要件は基本的に UploadPart と同じです。BeginIndex を使用して、アップロードする次のパートの開始に対応する位置を見つける必要があります。また、SourceKey でコピーするオブジェクトも指定する必要があります。

マルチパートアップロードの実行

以下のコードを使用してマルチパートアップロードを実行します。

  1. // Initialize OSSClient
  2. var client = new OssClient(endpoint, accessId, accessKey);
  3. var completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId);
  4. foreach (var partETag in partETags)
  5. {
  6. completeMultipartUploadRequest.PartETags.Add(partETag);
  7. }
  8. var result = client.CompleteMultipartUpload(completeMultipartUploadRequest);

上記のコードでは、マルチパートアップロード中に partETags が partETag リストに保存されます。ユーザーから送信されたパートリストを OSS が受信すると、各データパートの有効性が個別に検証されます。すべてのデータパートが検証されると、OSS はこれらのパートを 1 つの完全なオブジェクトに結合します。

マルチパートアップロードタスクのキャンセル

abortMultipartUpload メソッドを使用して、マルチパートアップロードタスクをキャンセルできます。

  1. // Initialize OSSClient
  2. var client = new OssClient(endpoint, accessId, accessKey);
  3. CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId);
  4. client.CompleteMultipartUpload(request);

バケットのすべてのマルチパートアップロードタスクの取得

listMultipartUploads メソッドを使用して、バケット内のすべてのアップロードタスクを取得できます。

  1. // Initialize OSSClient
  2. var client = new OssClient(endpoint, accessId, accessKey);
  3. // Gets all upload tasks in the bucket
  4. var request = new ListMultipartUploadsRequest(bucketName);
  5. var multipartUploadListing = client.ListMultipartUploads(request);
  6. // Get event information
  7. var multipartUploads = multipartUploadListing.MultipartUploads;
  8. foreach (var mu : multipartUploads)
  9. {
  10. Console.WriteLine("Key:" + mu.Key + ", UploadId:" + mu.UploadId);
  11. }
  12. var commonPrefixes = multipartUploadListing. CommonPrefixes;
  13. foreach (var prefix : commonPrefixes)
  14. {
  15. Console.WriteLine("Prefix:" + prefix);
  16. }

注意: 通常の状態で、バケットに 1000 を超えるマルチパートアップロードタスクが含まれる場合、最初の 1000 個が返され、返される結果の IsTruncated パラメーターは false になります。返される NextKeyMarker および NextUploadMarker は、データの読み取りを継続するための次の開始地点として使用できます。返されるマルチパートアップロードタスクの数を増やす場合は、MaxUploads パラメーターを変更するか、セグメント化された読み取りに KeyMarker および UploadIdMarker パラメーターを使用します。

アップロードされたすべてのパートの情報の取得

listParts メソッドを使用して、アップロードタスクでアップロードされたすべてのパートを取得できます。

  1. // Initialize OSSClient
  2. var client = new OssClient(endpoint, accessId, accessKey);
  3. var listPartsRequest = new ListPartsRequest(bucketName, objectName, uploadId);
  4. var listPartsResult = client.ListParts(listPartsRequest);
  5. // Traverses all parts
  6. var parts = listPartsResult.Parts;
  7. foreach (var part : parts)
  8. {
  9. Console.WriteLine("PartNumber:" + part. PartNumber + ", ETag:" + part. Etag +",Size:" + part.Size);
  10. }

注意: 通常の状態で、バケットに 1000 を超えるマルチパートアップロードタスクが含まれる場合、最初の 1000 個が返され、返される結果の IsTruncated パラメーターは false になります。返される NextPartNumberMarker は、データの読み取りを継続するための次の開始地点として使用できます。返されるマルチパートアップロードタスクの数を増やす場合は、MaxParts パラメーターを変更するか、セグメント化された読み取りに PartNumberMarker パラメーターを使用します。