すべてのプロダクト
Search
ドキュメントセンター

:MultipartUpload

最終更新日:Dec 22, 2023

マルチパートアップロード

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

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

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

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

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

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

String bucketName = "your-bucket-name";
String key = "your-key";

// Initialize OSSClient
var client = new OssClient(endpoint, accessId, accessKey);
// Starts Multipart Upload
var request = new InitiateMultipartUploadRequest(bucketName, objectName);
var result = client.InitiateMultipartUpload(request);
// Prints UploadId
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 にマルチパートアップロードする必要があります。

// Initialize OSSClient
var client = new OssClient(endpoint, accessId, accessKey);

var fi = new FileInfo(fileToUpload);
var fileSize = fi.Length;
var partCount = fileSize / partSize;
if (fileSize % partSize != 0)
{
     partCount++;
}
var partETags = new List<PartETag>();
for (var i = 0; i < partCount; i++)
{
     using (var fs = File.Open(fileToUpload, FileMode.Open))
     {
          var skipBytes = (long)partSize * i;
          fs.Seek(skipBytes, 0);
          var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
          var request = new UploadPartRequest(bucketName, objectName, uploadId)
          {
               InputStream = fs,
               PartSize = size,
               PartNumber = i + 1
           };
           var result = _ossClient.UploadPart(request);
           partETags.Add(result.PartETag);
       }
    }

このプログラムの主な目的は、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 メソッドを使用することをお勧めします。

// Initialize OSSClient
var client = new OssClient(endpoint, accessId, accessKey);

var metadata = client.GetObjectMetadata(sourceBucket, sourceObject);
var fileSize = metadata.ContentLength;

var partCount = (int)fileSize / partSize;
if (fileSize % partSize != 0)
{
     partCount++;
}

var partETags = new List<PartETag>();
for (var i = 0; i < partCount; i++)
{
     var skipBytes = (long)partSize * i;
     var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
     var request = new UploadPartCopyRequest(targetBucket, targetObject, sourceBucket, sourceObject, uploadId)
     {
           PartSize = size,
           PartNumber = i + 1,
           BeginIndex = skipBytes
     };
     var result = client.UploadPartCopy(request);
     partETags.Add(result.PartETag);
}

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

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

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

// Initialize OSSClient
var client = new OssClient(endpoint, accessId, accessKey);

var completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId);
foreach (var partETag in partETags)
{
     completeMultipartUploadRequest.PartETags.Add(partETag);
}
var result = client.CompleteMultipartUpload(completeMultipartUploadRequest);

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

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

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

// Initialize OSSClient
var client = new OssClient(endpoint, accessId, accessKey);

CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId);
client.CompleteMultipartUpload(request);

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

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

// Initialize OSSClient
var client = new OssClient(endpoint, accessId, accessKey);

// Gets all upload tasks in the bucket
var request = new ListMultipartUploadsRequest(bucketName);
var multipartUploadListing = client.ListMultipartUploads(request);
// Get event information
var multipartUploads = multipartUploadListing.MultipartUploads;
foreach (var mu : multipartUploads)
{
  Console.WriteLine("Key:" + mu.Key + ", UploadId:" + mu.UploadId);
}
var commonPrefixes = multipartUploadListing. CommonPrefixes;
foreach (var prefix : commonPrefixes)
{
  Console.WriteLine("Prefix:" + prefix);
}

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

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

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

// Initialize OSSClient
var client = new OssClient(endpoint, accessId, accessKey);

var listPartsRequest = new ListPartsRequest(bucketName, objectName, uploadId);
var listPartsResult = client.ListParts(listPartsRequest);

// Traverses all parts
var parts = listPartsResult.Parts;
foreach (var part : parts)
{
  Console.WriteLine("PartNumber:" + part. PartNumber + ", ETag:" + part. Etag +",Size:" + part.Size);
}

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