マルチパートアップロード
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 パラメーターを使用します。