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

Object Storage Service:マルチパートアップロード

最終更新日:Mar 22, 2025

5 GB を超えるオブジェクトをシンプルアップロードを使用してアップロードする場合、長時間を要する可能性があり、ネットワークの中断またはプログラムの例外が原因でオブジェクトのアップロードに失敗する可能性があります。この場合、オブジェクトを複数のパートに分割し、パートを並行してアップロードすることで、アップロードを高速化できます。特定のパートのアップロードに失敗した場合、そのパートのみを再アップロードする必要があります。

シナリオ

  • ラージオブジェクトの高速アップロード: 5 GB を超えるオブジェクトをアップロードする場合、マルチパートアップロードを使用してオブジェクトを複数のパートに分割し、パートを並行してアップロードすることで、アップロードを高速化できます。

  • ネットワークのジッター: マルチパートアップロードは、ネットワークの状態が悪いシナリオに適しています。特定のパートのアップロードに失敗した場合、そのパートのみを再アップロードする必要があります。これにより、時間と帯域幅が節約されます。

  • アップロードの一時停止と再開: マルチパートアップロードタスクは期限切れになりません。タスクが完了またはキャンセルされるまでは、いつでもマルチパートアップロードタスクを一時停止および再開できます。

  • 不明なオブジェクトサイズ: ビデオ監視などのシナリオでは、最終的なオブジェクトサイズが不明な場合があります。この場合、マルチパートアップロードを使用してオブジェクトをアップロードできます。

プロセス

マルチパートアップロードを使用してローカルファイルをアップロードするには、次の手順を実行します。

  1. InitiateMultipartUpload 操作を呼び出して、マルチパートアップロードタスクを開始します。

  2. UploadPart 操作を呼び出して、パートをアップロードします。

    • アップロードするオブジェクトのパートは、アップロード中に指定したパート番号に基づいてソートされます。ただし、パートは順番にアップロードする必要はなく、並行してアップロードできます。並行してアップロードされるパートが多いほど、必ずしもアップロードが高速化されるわけではありません。ネットワークの状態とデバイスのワークロードに基づいて、並列アップロードの数を指定することをお勧めします。

    • デフォルトでは、オブジェクトのパートをアップロードしても CompleteMultipartUpload 操作を呼び出してパートをオブジェクトに結合しない場合、アップロードされたパートは自動的には削除されません。アップロードタスクをキャンセルしてパートを削除するには、AbortMultipartUpload 操作を呼び出します。

  3. CompleteMultipartUpload 操作を呼び出して、アップロードされたパートをオブジェクトに結合します。

メソッド

説明

OSS コンソールではマルチパートアップロードを実行できません。5 GB を超えるオブジェクトをアップロードする場合は、ossbrowser、OSS SDK、または ossutil を使用してください。

ossutil を使用する

ossutil 2.0 が提供する cp コマンドを実行して大きなローカルファイルをアップロードすると、ossutil は自動的にマルチパートアップロードを使用してローカルファイルをアップロードします。

ossutil cp D:/localpath/example.iso oss://examplebucket/desfolder/

マルチパートアップロードを使用してローカルファイルを手動でアップロードするには、initiate-multipart-uploadupload-part、および complete-multipart-upload 操作を一緒に使用できます。

OSS SDK を使用する

Java

次のサンプルコードは、OSS SDK for Java を使用してマルチパートアップロードを実装する方法の例を示しています。

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.internal.Mimetypes;
import com.aliyun.oss.model.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class Demo {

    public static void main(String[] args) throws Exception {
        // この例では、中国 (杭州) リージョンのエンドポイントが使用されています。実際のエンドポイントを指定してください。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が構成されていることを確認してください。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // バケットの名前を指定します。例: examplebucket。
        String bucketName = "examplebucket";
        // オブジェクトのフルパスを指定します。例: exampledir/exampleobject.txt。フルパスにバケット名を含めないでください。
        String objectName = "exampledir/exampleobject.txt";
        // アップロードするローカルファイルのフルパスを指定します。
        String filePath = "D:\\localpath\\examplefile.txt";
        // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。
        String region = "cn-hangzhou";

        // OSSClient インスタンスを作成します。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            // InitiateMultipartUploadRequest オブジェクトを作成します。
            InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);

            // ObjectMetadata オブジェクトを作成し、Content-Type パラメーターを指定します。
            ObjectMetadata metadata = new ObjectMetadata();
            if (metadata.getContentType() == null) {
                metadata.setContentType(Mimetypes.getInstance().getMimetype(new File(filePath), objectName));
            }
            System.out.println("Content-Type: " + metadata.getContentType());

            // メタデータをアップロードリクエストにバインドします。
            request.setObjectMetadata(metadata);

            // マルチパートアップロードタスクを初期化します。
            InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
            // アップロード ID を取得します。
            String uploadId = upresult.getUploadId();

            // partETags は PartETag のセットです。PartETag は、アップロードされたパートのパート番号と ETag で構成されます。
            List<PartETag> partETags = new ArrayList<PartETag>();
            // 各パートのサイズを指定します。これは、オブジェクトのパート数を計算するために使用されます。単位: バイト。
            final long partSize = 1 * 1024 * 1024L;   // パートサイズを 1 MB に設定します。

            // アップロードされたデータのサイズに基づいてパート数を計算します。次のサンプルコードでは、ローカルファイルを例として、File.length() メソッドを使用してアップロードされたデータのサイズを取得する方法について説明します。
            final File sampleFile = new File(filePath);
            long fileLength = sampleFile.length();
            int partCount = (int) (fileLength / partSize);
            if (fileLength % partSize != 0) {
                partCount++;
            }
            // すべてのパートがアップロードされるまで、各パートをアップロードします。
            for (int i = 0; i < partCount; i++) {
                long startPos = i * partSize;
                long curPartSize = (i + 1 == partCount) ?  (fileLength - startPos) : partSize;
                UploadPartRequest uploadPartRequest = new UploadPartRequest();
                uploadPartRequest.setBucketName(bucketName);
                uploadPartRequest.setKey(objectName);
                uploadPartRequest.setUploadId(uploadId);
                // マルチパートアップロードタスクの入力ストリームを指定します。
                // 次のサンプルコードでは、ローカルファイルを例として、FileInputStream オブジェクトを作成し、InputStream.skip() メソッドを使用して指定されたデータをスキップする方法について説明します。
                InputStream instream = new FileInputStream(sampleFile);
                instream.skip(startPos);
                uploadPartRequest.setInputStream(instream);
                // 各パートで使用可能なサイズを指定します。最後のパートを除く各パートのサイズは、100 KB 以上である必要があります。
                uploadPartRequest.setPartSize(curPartSize);
                // パート番号を指定します。各パートには、1 から 10,000 までのパート番号があります。指定したパート番号が指定された範囲内にない場合、OSS は InvalidArgument エラーコードを返します。
                uploadPartRequest.setPartNumber(i + 1);
                // パートは必ずしも順番にアップロードする必要はなく、異なる OSS クライアントからアップロードできます。OSS はパート番号に基づいてパートをソートし、パートを完全なオブジェクトに結合します。
                UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
                // パートがアップロードされると、OSS は PartETag を含む結果を返します。PartETag は partETags に格納されます。
                partETags.add(uploadPartResult.getPartETag());

                // 入力ストリームを無効にします。
                instream.close();
            }

            // CompleteMultipartUploadRequest オブジェクトを作成します。
            // CompleteMultipartUpload 操作を呼び出すときは、すべての有効な partETag を指定する必要があります。OSS は PartETag を受信した後、すべてのパートを 1 つずつ検証します。すべてのパートが検証されると、OSS はこれらのパートを完全なオブジェクトに結合します。
            CompleteMultipartUploadRequest completeMultipartUploadRequest =
                    new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);

            // マルチパートアップロードタスクを完了します。
            CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
            System.out.println("アップロード成功、ETag:" + completeMultipartUploadResult.getETag());

        } catch (OSSException oe) {
            System.out.println("OSSException が発生しました。これは、リクエストが OSS に到達しましたが、"
                    + "何らかの理由でエラー応答で拒否されたことを意味します。");
            System.out.println("エラーメッセージ:" + oe.getErrorMessage());
            System.out.println("エラーコード:" + oe.getErrorCode());
            System.out.println("リクエスト ID:" + oe.getRequestId());
            System.out.println("ホスト ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("ClientException が発生しました。これは、クライアントが OSS と通信しようとしているときに "
                    + "深刻な内部問題が発生したことを意味します。"
                    + "たとえば、ネットワークにアクセスできないなどです。");
            System.out.println("エラーメッセージ:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

他のシナリオのサンプルコードについては、「マルチパートアップロード」をご参照ください。

PHP

次のサンプルコードは、OSS SDK for PHP を使用してマルチパートアップロードを実装する方法の例を示しています。

<?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;
use OSS\Core\OssUtil;

// 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が構成されていることを確認してください。
$provider = new EnvironmentVariableCredentialsProvider();
// この例では、中国 (杭州) リージョンのエンドポイントが使用されています。実際のエンドポイントを指定してください。
$endpoint = 'https://oss-cn-hangzhou.aliyuncs.com';
// バケットの名前を指定します。例: examplebucket。
$bucket= 'examplebucket';
// オブジェクトのフルパスを指定します。フルパスにバケット名を含めないでください。例: exampledir/exampleobject.txt。
$object = 'exampledir/exampleobject.txt';
// アップロードするローカルファイルのフルパスを指定します。
$uploadFile = 'D:\\localpath\\examplefile.txt';
$initOptions = array(
    OssClient::OSS_HEADERS  => array(
        // オブジェクトのダウンロード時に Web ページのキャッシュ動作を指定します。
        // 'Cache-Control' => 'no-cache',
        // オブジェクトのダウンロード時にオブジェクトの名前を指定します。
        // 'Content-Disposition' => 'attachment;filename=oss_download.jpg',
        // リクエストの有効期間を指定します。単位: ミリ秒。
        // 'Expires' => 150,
        // マルチパートアップロードタスクの初期化時に、マルチパートアップロードを使用してアップロードされたオブジェクトが、同じ名前の既存のオブジェクトを上書きするかどうかを指定します。この例では、このパラメーターは true に設定されており、アップロードされたオブジェクトが既存のオブジェクトと同じ名前の場合、既存のオブジェクトを上書きしないことを指定しています。
        //'x-oss-forbid-overwrite' => 'true',
        // オブジェクトの各パートの暗号化に使用するサーバー側暗号化方式を指定します。
        // 'x-oss-server-side-encryption'=> 'KMS',
        // オブジェクトの暗号化に使用するアルゴリズムを指定します。
        // 'x-oss-server-side-data-encryption'=>'SM4',
        // Key Management Service (KMS) によって管理されるカスタマーマスターキー (CMK) の ID を指定します。
        //'x-oss-server-side-encryption-key-id' => '9468da86-3509-4f8d-a61e-6eab1eac****',
        // オブジェクトのストレージタイプを指定します。
        // 'x-oss-storage-class' => 'Standard',
        // オブジェクトのタグを指定します。オブジェクトに複数のタグを一度に指定できます。
        // 'x-oss-tagging' => 'TagA=A&TagB=B',
    ),
);

/**
 * ステップ 1: マルチパートアップロードタスクを開始し、アップロード ID を取得します。
 */
try{
    $config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
        "signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
        "region"=> "cn-hangzhou"
    );
    $ossClient = new OssClient($config);
    // アップロード ID を取得します。アップロード ID は、マルチパートアップロードタスクの一意の識別子です。アップロード ID に基づいて、マルチパートアップロードタスクのキャンセルやクエリなどの関連操作を実行できます。
    $uploadId = $ossClient->initiateMultipartUpload($bucket, $object, $initOptions);
    print("initiateMultipartUpload OK" . "\n");
    // アップロード ID に基づいてマルチパートアップロードタスクをキャンセルするか、アップロードされたパートを一覧表示します。
    // アップロード ID に基づいてマルチパートアップロードタスクをキャンセルする場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後に、アップロード ID を取得します。
    // アップロード ID に基づいてマルチパートアップロードタスクでアップロードされたパートを一覧表示する場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後で、CompleteMultipartUpload 操作を呼び出してマルチパートアップロードタスクを完了する前に、アップロード ID を取得します。
    //print("UploadId: " . $uploadId . "\n");
} catch(OssException $e) {
    printf($e->getMessage() . "\n");
    return;
}

/*
 * ステップ 2: パートをアップロードします。
 */
$partSize = 10 * 1024 * 1024;
$uploadFileSize = sprintf('%u',filesize($uploadFile));
$pieces = $ossClient->generateMultiuploadParts($uploadFileSize, $partSize);
$responseUploadPart = array();
$uploadPosition = 0;
$isCheckMd5 = true;
foreach ($pieces as $i => $piece) {
    $fromPos = $uploadPosition + (integer)$piece[$ossClient::OSS_SEEK_TO];
    $toPos = (integer)$piece[$ossClient::OSS_LENGTH] + $fromPos - 1;
    $upOptions = array(
        // オブジェクトをアップロードします。
        $ossClient::OSS_FILE_UPLOAD => $uploadFile,
        // パート番号を指定します。
        $ossClient::OSS_PART_NUM => ($i + 1),
        // マルチパートアップロードタスクの開始位置を指定します。
        $ossClient::OSS_SEEK_TO => $fromPos,
        // オブジェクトの長さを指定します。
        $ossClient::OSS_LENGTH => $toPos - $fromPos + 1,
        // MD5 検証を有効にするかどうかを指定します。値 true は、MD5 検証が有効になっていることを指定します。
        $ossClient::OSS_CHECK_MD5 => $isCheckMd5,
    );
    // MD5 検証を有効にします。
    if ($isCheckMd5) {
        $contentMd5 = OssUtil::getMd5SumForFile($uploadFile, $fromPos, $toPos);
        $upOptions[$ossClient::OSS_CONTENT_MD5] = $contentMd5;
    }
    try {
        // パートをアップロードします。
        $responseUploadPart[] = $ossClient->uploadPart($bucket, $object, $uploadId, $upOptions);
        printf("initiateMultipartUpload, uploadPart - part#{$i} OK\n");
    } catch(OssException $e) {
        printf("initiateMultipartUpload, uploadPart - part#{$i} FAILED\n");
        printf($e->getMessage() . "\n");
        return;
    }

}
// $uploadParts は、各パートの ETag とパート番号で構成される配列です。
$uploadParts = array();
foreach ($responseUploadPart as $i => $eTag) {
    $uploadParts[] = array(
        'PartNumber' => ($i + 1),
        'ETag' => $eTag,
    );
}
/**
 * ステップ 3: マルチパートアップロードタスクを完了します。
 */
$comOptions['headers'] = array(
    // マルチパートアップロードタスクの完了時に、マルチパートアップロードを使用してアップロードされたオブジェクトが、同じ名前の既存のオブジェクトを上書きするかどうかを指定します。この例では、このパラメーターは true に設定されており、アップロードされたオブジェクトが既存のオブジェクトと同じ名前の場合、既存のオブジェクトを上書きしないことを指定しています。
    // 'x-oss-forbid-overwrite' => 'true',
    // x-oss-complete-all パラメーターを yes に設定すると、OSS は現在のアップロード ID を使用してアップロードされたすべてのパートを一覧表示し、パート番号でパートをソートしてから、CompleteMultipartUpload 操作を実行します。
    // 'x-oss-complete-all'=> 'yes'
);

try {
    // CompleteMultipartUpload 操作には、$uploadParts パラメーターのすべての有効な値が必要です。OSS は $uploadParts パラメーターの値を受信した後、すべてのパートを 1 つずつ検証します。すべてのパートが検証されると、OSS はパートを完全なオブジェクトに結合します。
    $ossClient->completeMultipartUpload($bucket, $object, $uploadId, $uploadParts,$comOptions);
    printf( "Complete Multipart Upload OK\n");
}  catch(OssException $e) {
    printf("Complete Multipart Upload FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
           

Node.js

次のサンプルコードは、OSS SDK for Node.js を使用してマルチパートアップロードを実装する方法の例を示しています。

const OSS = require('ali-oss');
const path = require("path");

const client = new OSS({
  // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを oss-cn-hangzhou に設定します。
  region: 'yourregion',
  // 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が構成されていることを確認してください。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // バケットの名前を指定します。
  bucket: 'yourbucketname',
});


const progress = (p, _checkpoint) => {
  // オブジェクトのアップロードの進捗状況を記録します。
  console.log(p); 
  // マルチパートアップロードタスクに関するチェックポイント情報を記録します。
  console.log(_checkpoint); 
};

const headers = {  
  // オブジェクトのストレージタイプを指定します。
  'x-oss-storage-class': 'Standard', 
  // オブジェクトのタグを指定します。オブジェクトに複数のタグを指定できます。
  'x-oss-tagging': 'Tag1=1&Tag2=2', 
  // マルチパートアップロードタスクの初期化時に、同じ名前の既存のオブジェクトを上書きするかどうかを指定します。この例では、このパラメーターは true に設定されており、アップロードするオブジェクトと同じ名前の既存のオブジェクトは上書きされないことを示しています。
  'x-oss-forbid-overwrite': 'true'
}

// マルチパートアップロードタスクを開始します。
async function multipartUpload() {
  try {
    // オブジェクトのフルパスを指定します。例: exampledir/exampleobject.txt。次に、ローカルファイルのフルパスを指定します。例: D:\\localpath\\examplefile.txt。フルパスにバケット名を含めないでください。
    // デフォルトでは、このパラメーターをローカルパスの指定なしで examplefile.txt などのローカルファイルの名前に設定すると、ローカルファイルはサンプルプログラムが属するプロジェクトのローカルパスからアップロードされます。
    const result = await client.multipartUpload('exampledir/exampleobject.txt', path.normalize('D:\\localpath\\examplefile.txt'), {
      progress,
      // headers,
      // meta パラメーターを構成して、オブジェクトのメタデータを指定します。HeadObject 操作を呼び出して、オブジェクトメタデータを取得できます。
      meta: {
        year: 2020,
        people: 'test',
      },
    });
    console.log(result);
    // オブジェクトのフルパスを指定します。例: exampledir/exampleobject.txt。フルパスにバケット名を含めないでください。
    const head = await client.head('exampledir/exampleobject.txt');
    console.log(head);
  } catch (e) {
    // タイムアウト例外を処理します。
    if (e.code === 'ConnectionTimeoutError') {
      console.log('TimeoutError');
      // ConnectionTimeoutError 操作を実行します
    }
    console.log(e);
  }
}

multipartUpload();

Python

次のサンプルコードは、OSS SDK for Python を使用してマルチパートアップロードを実装する方法の例を示しています。

# -*- coding: utf-8 -*-
import os
from oss2 import SizedFileAdapter, determine_part_size
from oss2.models import PartInfo
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が構成されていることを確認してください。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

# バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"

# エンドポイントにマップするリージョンの ID を指定します。例: cn-hangzhou。署名アルゴリズム V4 を使用する場合は、このパラメーターが必要です。
region = "cn-hangzhou"

# バケットの名前を指定します。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)

// オブジェクトのフルパスを指定します。フルパスにバケット名を含めないでください。例: exampledir/exampleobject.txt。
key = 'exampledir/exampleobject.txt'
// アップロードするローカルファイルのフルパスを指定します。例: D:\\localpath\\examplefile.txt。
filename = 'D:\\localpath\\examplefile.txt'

total_size = os.path.getsize(filename)
// determine_part_size メソッドを使用して、パートサイズを決定します。
part_size = determine_part_size(total_size, preferred_size=100 * 1024)

// マルチパートアップロードタスクを開始します。
// マルチパートアップロードタスクの開始時にオブジェクトのストレージタイプを指定する場合は、init_multipart_upload メソッドを使用するときに関連するヘッダーを構成します。
// headers = dict()
// オブジェクトの Web ページのキャッシュ動作を指定します。
// headers['Cache-Control'] = 'no-cache'
// ダウンロード時にオブジェクトの名前を指定します。
// headers['Content-Disposition'] = 'oss_MultipartUpload.txt'
// 有効期間を指定します。単位: ミリ秒。
// headers['Expires'] = '1000'
// マルチパートアップロードタスクの開始時に、マルチパートアップロードを実行してアップロードされたオブジェクトが、同じ名前の既存のオブジェクトを上書きするかどうかを指定します。この例では、このパラメーターは true に設定されており、同じ名前のオブジェクトを上書きできないことを示しています。
// headers['x-oss-forbid-overwrite'] = 'true'
// 各パートの暗号化に使用するサーバー側暗号化方式を指定します。
// headers[OSS_SERVER_SIDE_ENCRYPTION] = SERVER_SIDE_ENCRYPTION_KMS
// オブジェクトの暗号化に使用するアルゴリズムを指定します。このパラメーターを構成しない場合、オブジェクトは AES-256 を使用して暗号化されます。
// headers[OSS_SERVER_SIDE_DATA_ENCRYPTION] = SERVER_SIDE_ENCRYPTION_KMS
// Key Management Service (KMS) によって管理されるカスタマーマスターキー (CMK) の ID を指定します。
// headers[OSS_SERVER_SIDE_ENCRYPTION_KEY_ID] = '9468da86-3509-4f8d-a61e-6eab1eac****'
// オブジェクトのストレージタイプを指定します。
// headers['x-oss-storage-class'] = oss2.BUCKET_STORAGE_CLASS_STANDARD
// オブジェクトのタグを指定します。オブジェクトに複数のタグを同時に指定できます。
// headers[OSS_OBJECT_TAGGING] = 'k1=v1&k2=v2&k3=v3'
// upload_id = bucket.init_multipart_upload(key, headers=headers).upload_id
upload_id = bucket.init_multipart_upload(key).upload_id
// アップロード ID に基づいてマルチパートアップロードタスクをキャンセルするか、アップロードされたパートを一覧表示します。
// アップロード ID に基づいてマルチパートアップロードタスクをキャンセルする場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後に、アップロード ID を取得します。
// アップロード ID に基づいてマルチパートアップロードタスクでアップロードされたパートを一覧表示する場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後で、CompleteMultipartUpload 操作を呼び出してマルチパートアップロードタスクを完了する前に、アップロード ID を取得します。
// print("UploadID:", upload_id)
parts = []

// パートをアップロードします。
with open(filename, 'rb') as fileobj:
    part_number = 1
    offset = 0
    while offset < total_size:
        num_to_upload = min(part_size, total_size - offset)
        // SizedFileAdapter(fileobj, size) メソッドを使用して新しいオブジェクトを生成し、追加操作の開始位置を再計算します。
        result = bucket.upload_part(key, upload_id, part_number,
                                    SizedFileAdapter(fileobj, num_to_upload))
        parts.append(PartInfo(part_number, result.etag))

        offset += num_to_upload
        part_number += 1

// マルチパートアップロードタスクを完了します。
// マルチパートアップロードタスクの完了時にヘッダーを構成します(必要な場合)。
headers = dict()
// オブジェクトのアクセス制御リスト (ACL) を指定します。この例では、ACL は OBJECT_ACL_PRIVATE に設定されており、オブジェクトの ACL が非公開であることを示しています。
// headers["x-oss-object-acl"] = oss2.OBJECT_ACL_PRIVATE
bucket.complete_multipart_upload(key, upload_id, parts, headers=headers)
// bucket.complete_multipart_upload(key, upload_id, parts)

Browser.js

次のサンプルコードは、OSS SDK for Browser.js を使用してマルチパートアップロードを実装する方法の例を示しています。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>ドキュメント</title>
  </head>

  <body>
    <button id="submit">アップロード</button>
    <input id="file" type="file" />
    <!-- SDK ファイルをインポートします -->
    <script
      type="text/javascript"
      src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
    ></script>
    <script type="text/javascript">
      const client = new OSS({
        // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを oss-cn-hangzhou に設定します。
        region: "yourRegion",
        authorizationV4: true,
        // STS から取得した一時的な AccessKey ペアを指定します。AccessKey ペアは、AccessKey ID と AccessKey シークレットで構成されます。
        accessKeyId: "yourAccessKeyId",
        accessKeySecret: "yourAccessKeySecret",
        // STS から取得したセキュリティトークンを指定します。
        stsToken: "yourSecurityToken",
        // バケットの名前を指定します。例: examplebucket。
        bucket: "examplebucket",
      });

      const headers = {
        // オブジェクトのダウンロード時に Web ページのキャッシュ動作を指定します。
        "Cache-Control": "no-cache",
        // オブジェクトのダウンロード時にオブジェクトの名前を指定します。
        "Content-Disposition": "example.txt",
        // リクエストの有効期間を指定します。単位: ミリ秒。
        Expires: "1000",
        // オブジェクトのストレージタイプを指定します。
        "x-oss-storage-class": "Standard",
        // オブジェクトに 1 つ以上のタグを指定します。
        "x-oss-tagging": "Tag1=1&Tag2=2",
        // マルチパートアップロードタスクの初期化時に、同じ名前の既存のオブジェクトを上書きするかどうかを指定します。この例では、x-oss-forbid-overwrite パラメーターは true に設定されています。この値は、既存のオブジェクトを同じ名前のオブジェクトで上書きできないことを指定します。
        "x-oss-forbid-overwrite": "true",
      };

      // examplebucket バケットにアップロードされるオブジェクトの名前を指定します。例: exampleobject.txt。
      const name = "exampleobject.txt";
      // DOM を取得します。
      const submit = document.getElementById("submit");
      const options = {
        // マルチパートアップロードタスクの進捗状況、チェックポイント、および戻り値をクエリします。
        progress: (p, cpt, res) => {
          console.log(p);
        },
        // 並行してアップロードできるパートの数を指定します。
        parallel: 4,
        // パートサイズを指定します。デフォルト値: 1 MB。最小値: 100 KB。
        partSize: 1024 * 1024,
        // headers,
        // オブジェクトのユーザーメタデータを指定します。HeadObject 操作を呼び出して、オブジェクトメタデータをクエリできます。
        meta: { year: 2020, people: "test" },
        mime: "text/plain",
      };

      // イベントリスナーを構成します。
      submit.addEventListener("click", async () => {
        try {
          const data = document.getElementById("file").files[0];
          // マルチパートアップロードタスクを開始します。
          const res = await client.multipartUpload(name, data, {
            ...options,
            // アップロードコールバックを構成します。
            // コールバックサーバーが不要な場合は、コールバック構成を削除します。
            callback: {
              // コールバックリクエストを受信するサーバーのアドレスを指定します。
              url: "http://examplebucket.aliyuncs.com:23450",
              // コールバックリクエストの Host ヘッダーを指定します。
              host: "yourHost",
              /* eslint no-template-curly-in-string: [0] */
              // コールバックリクエストの本文コンテンツを指定します。
              body: "bucket=${bucket}&object=${object}&var1=${x:var1}",
              // コールバックリクエストの Content-Type を指定します。
              contentType: "application/x-www-form-urlencoded",
              customValue: {
                // コールバックリクエストのカスタムパラメーターを指定します。
                var1: "value1",
                var2: "value2",
              },
            },
          });
          console.log(res);
        } catch (err) {
          console.log(err);
        }
      });
    </script>
  </body>
</html>

C#

次のサンプルコードは、OSS SDK for C# を使用してマルチパートアップロードを実装する方法の例を示しています。

using Aliyun.OSS;
using Aliyun.OSS.Common;

// バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
var endpoint = "yourEndpoint";
// 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が構成されていることを確認してください。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// バケットの名前を指定します。
var bucketName = "examplebucket";
// オブジェクトのフルパスを指定します。フルパスにバケット名を含めないでください。
var objectName = "exampleobject.txt";
// アップロードするローカルファイルのフルパスを指定します。デフォルトでは、ローカルファイルのフルパスを指定しないと、ローカルファイルはサンプルプログラムが属するプロジェクトのパスからアップロードされます。
var localFilename = "D:\\localpath\\examplefile.txt";
// バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。
const string region = "cn-hangzhou";

// ClientConfiguration インスタンスを作成し、要件に基づいてデフォルトパラメーターを変更します。
var conf = new ClientConfiguration();

// 署名アルゴリズム V4 を使用します。
conf.SignatureVersion = SignatureVersion.V4;

// OSSClient インスタンスを作成します。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);

// マルチパートアップロードタスクを開始し、レスポンスでアップロード ID を取得します。
var uploadId = "";
try
{
    // アップロードされたオブジェクトの名前とオブジェクトのバケットを指定します。InitiateMultipartUploadRequest でオブジェクトメタデータを構成できます。ただし、ContentLength を指定する必要はありません。
    var request = new InitiateMultipartUploadRequest(bucketName, objectName);
    var result = client.InitiateMultipartUpload(request);
    uploadId = result.UploadId;
    // アップロード ID を表示します。
    Console.WriteLine("マルチパートアップロードの初期化に成功しました");
    // アップロード ID に基づいてマルチパートアップロードタスクをキャンセルするか、アップロードされたパートを一覧表示します。
    // アップロード ID に基づいてマルチパートアップロードタスクをキャンセルする場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後に、アップロード ID を取得します。
    // アップロード ID に基づいてマルチパートアップロードタスクでアップロードされたパートを一覧表示する場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後で、CompleteMultipartUpload 操作を呼び出してマルチパートアップロードタスクを完了する前に、アップロード ID を取得します。
    Console.WriteLine("アップロード ID:{0}", result.UploadId);
}
catch (Exception ex)
{
    Console.WriteLine("マルチパートアップロードの初期化に失敗しました、{0}", ex.Message);
    Environment.Exit(1);
}
// パートの総数を計算します。
var partSize = 100 * 1024;
var fi = new FileInfo(localFilename);
var fileSize = fi.Length;
var partCount = fileSize / partSize;
if (fileSize % partSize != 0)
{
    partCount++;
}
// パートを初期化し、マルチパートアップロードタスクを開始します。partETags は PartETag のリストです。OSS は partETag を受信した後、すべてのパートを 1 つずつ検証します。すべてのパートが検証されると、OSS はこれらのパートを完全なオブジェクトに結合します。
var partETags = new List<PartETag>();
try
{
    using (var fs = File.Open(localFilename, FileMode.Open))
    {
        for (var i = 0; i < partCount; i++)
        {
            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
            };
            // UploadPart を呼び出してパートをアップロードします。返された結果には、パートの ETag 値が含まれています。
            var result = client.UploadPart(request);
            partETags.Add(result.PartETag);
            Console.WriteLine("完了 {0}/{1}", partETags.Count, partCount);
        }
        Console.WriteLine("マルチパートアップロードに成功しました");
    }
}
catch (Exception ex)
{
    Console.WriteLine("マルチパートアップロードに失敗しました、{0}", ex.Message);
    Environment.Exit(1);
}
// パートがアップロードされたら、パートを結合します。
try
{
    var completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId);
    foreach (var partETag in partETags)
    {
        completeMultipartUploadRequest.PartETags.Add(partETag);
    }
    var result = client.CompleteMultipartUpload(completeMultipartUploadRequest);
    Console.WriteLine("マルチパートの完了に成功しました");
}
catch (Exception ex)
{
    Console.WriteLine("マルチパートの完了に失敗しました、{0}", ex.Message);
    Environment.Exit(1);
}

Android

次のサンプルコードは、OSS SDK for Android を使用してマルチパートアップロードを実装する方法の例を示しています。

// バケットの名前を指定します。例: 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);
// アップロード ID を取得します。
String uploadId = initResult.getUploadId();
// アップロード ID に基づいてマルチパートアップロードタスクをキャンセルするか、アップロードされたパートを一覧表示します。
// アップロード ID に基づいてマルチパートアップロードタスクをキャンセルする場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後に、アップロード ID を取得します。
// アップロード ID に基づいてマルチパートアップロードタスクでアップロードされたパートを一覧表示する場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後で、CompleteMultipartUpload 操作を呼び出してマルチパートアップロードタスクを完了する前に、アップロード ID を取得します。
// Log.d("uploadId", uploadId);

// パートサイズを指定します。単位: バイト。有効な値: 100 KB から 5 GB。
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 から 10000。
    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() で servercallback の結果を確認できます。
complete.setCallbackParam(new HashMap<String, String>() {
    {
        put("callbackUrl", CALLBACK_SERVER); // CALLBACK_SERVER パラメーターをサーバーアドレスに設定します。
        put("callbackBody", "test");
    }
});
CompleteMultipartUploadResult completeResult = oss.completeMultipartUpload(complete);
OSSLog.logError("-------------- serverCallback: " + completeResult.getServerCallbackReturnBody());

Go

次のサンプルコードは、OSS SDK for Go を使用してマルチパートアップロードを実装する方法の例を示しています。

package main

import (
	"bufio"
	"bytes"
	"context"
	"flag"
	"io"
	"log"
	"os"
	"sync"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// グローバル変数を定義します。
var (
	region     string // バケットが配置されているリージョン。
	bucketName string // バケットの名前。
	objectName string // オブジェクトの名前。

)

// コマンドラインパラメーターを初期化するために使用される init 関数を指定します。
func init() {
	flag.StringVar(&region, "region", "", "バケットが配置されているリージョン。")
	flag.StringVar(&bucketName, "bucket", "", "ソースバケットの名前。")
	flag.StringVar(&objectName, "object", "", "ソースオブジェクトの名前。")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// アップロード ID を指定します。
	var uploadId string

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、ソースバケット名が必要です")
	}

	// バケットが配置されているリージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、リージョンが必要です")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、ソースオブジェクト名が必要です")
	}

	// デフォルトの構成を読み込み、認証情報プロバイダーとリージョンを指定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSSClient インスタンスを作成します。
	client := oss.NewClient(cfg)

	// マルチパートアップロードタスクを開始するためのリクエストを作成します。
	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}
	initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)
	if err != nil {
		log.Fatalf("マルチパートアップロードの開始に失敗しました %v", err)
	}

	// マルチパートアップロードタスクを開始した結果を表示します。
	log.Printf("マルチパートアップロードの結果を開始します:%#v\n", *initResult.UploadId)
	uploadId = *initResult.UploadId

	// 待機グループとミューテックスを初期化します。
	var wg sync.WaitGroup
	var parts []oss.UploadPart
	count := 3
	var mu sync.Mutex

	// ローカルファイルからメモリにデータを読み込み、yourLocalFile をファイル名を含むローカルファイルの実際のパスに置き換えます。
	file, err := os.Open("yourLocalFile")
	if err != nil {
		log.Fatalf("ローカルファイルを開けませんでした %v", err)
	}
	defer file.Close()

	bufReader := bufio.NewReader(file)
	content, err := io.ReadAll(bufReader)
	if err != nil {
		log.Fatalf("ローカルファイルの読み取りに失敗しました %v", err)
	}
	log.Printf("ファイルサイズ: %d\n", len(content))

	// 各パートのサイズを計算します。
	chunkSize := len(content) / count
	if chunkSize == 0 {
		chunkSize = 1
	}

	// マルチパートアップロードタスクの複数のゴルーチンを開始します。
	for i := 0; i < count; i++ {
		start := i * chunkSize
		end := start + chunkSize
		if i == count-1 {
			end = len(content)
		}

		wg.Add(1)
		go func(partNumber int, start, end int) {
			defer wg.Done()

			// パートをアップロードするためのリクエストを作成します。
			partRequest := &oss.UploadPartRequest{
				Bucket:     oss.Ptr(bucketName),                 // バケットの名前。
				Key:        oss.Ptr(objectName),                 // オブジェクトの名前。
				PartNumber: int32(partNumber),                   // パート番号。
				UploadId:   oss.Ptr(uploadId),                   // アップロード ID。
				Body:       bytes.NewReader(content[start:end]), // パートのコンテンツ。
			}

			// パートをアップロードするためのリクエストを送信します。
			partResult, err := client.UploadPart(context.TODO(), partRequest)
			if err != nil {
				log.Fatalf("パートのアップロードに失敗しました %d: %v", partNumber, err)
			}

			// パートアップロードリクエストの結果を表示します。
			part := oss.UploadPart{
				PartNumber: partRequest.PartNumber,
				ETag:       partResult.ETag,
			}

			// ミューテックスを使用して共有データを保護します。
			mu.Lock()
			parts = append(parts, part)
			mu.Unlock()
		}(i+1, start, end)
	}

	// すべてのゴルーチンが完了するまで待ちます。
	wg.Wait()

	// マルチパートアップロードタスクを完了します。
	request := &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		UploadId: oss.Ptr(uploadId),
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts,
		},
	}
	result, err := client.CompleteMultipartUpload(context.TODO(), request)
	if err != nil {
		log.Fatalf("マルチパートアップロードの完了に失敗しました %v", err)
	}

	// マルチパートアップロードタスクの結果を表示します。
	log.Printf("マルチパートアップロードの結果を完了します:%#v\n", result)
}

Object C

次のサンプルコードは、OSS SDK for Object C を使用してマルチパートアップロードを実装する方法の例を示しています。

__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(@"マルチパートアップロードに失敗しました、エラー: %@", 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(@"パートのアップロードエラー: %@", 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];

C++

次のサンプルコードは、OSS SDK for C++ を使用してマルチパートアップロードを実装する方法の例を示しています。

#include <alibabacloud/oss/OssClient.h>
#include <fstream>

int64_t getFileSize(const std::string& file)
{
    std::fstream f(file, std::ios::in | std::ios::binary);
    f.seekg(0, f.end);
    int64_t size = f.tellg();
    f.close();
    return size;
}

using namespace AlibabaCloud::OSS;

int main(void)
{
    /* OSS へのアクセスに使用するアカウントに関する情報を初期化します。 */
    
    /* バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。 */
    std::string Endpoint = "yourEndpoint";
    /* バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。 */
    std::string Region = "yourRegion";
    /* バケットの名前を指定します。例: examplebucket。 */
    std::string BucketName = "examplebucket";
    /* オブジェクトのフルパスを指定します。オブジェクトのフルパスにバケット名を含めないでください。例: exampledir/exampleobject.txt。 */
    std::string ObjectName = "exampledir/exampleobject.txt";

    /* ネットワークリソースなどのリソースを初期化します。 */
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が構成されていることを確認してください。 */
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);
  
    InitiateMultipartUploadRequest initUploadRequest(BucketName, ObjectName);
    /* (オプション) ストレージタイプを指定します。 */
    //initUploadRequest.MetaData().addHeader("x-oss-storage-class", "Standard");

    /* マルチパートアップロードタスクを開始します。 */
    auto uploadIdResult = client.InitiateMultipartUpload(initUploadRequest);
    /* アップロード ID に基づいてマルチパートアップロードタスクをキャンセルするか、アップロードされたパートを一覧表示します。 */
    /* アップロード ID に基づいてマルチパートアップロードタスクをキャンセルする場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後に、アップロード ID を取得します。 */
    /* アップロード ID に基づいてマルチパートアップロードタスクでアップロードされたパートを一覧表示する場合は、InitiateMultipartUpload 操作を呼び出してマルチパートアップロードタスクを開始した後で、CompleteMultipartUpload 操作を呼び出してマルチパートアップロードタスクを完了する前に、アップロード ID を取得します。 */
    auto uploadId = uploadIdResult.result().UploadId();
    std::string fileToUpload = "yourLocalFilename";
    int64_t partSize = 100 * 1024;
    PartList partETagList;
    auto fileSize = getFileSize(fileToUpload);
    int partCount = static_cast<int>(fileSize / partSize);
    /* パートの数を計算します。 */
    if (fileSize % partSize != 0) {
        partCount++;
    }

    /* 各パートをアップロードします。 */
    for (int i = 1; i <= partCount; i++) {
        auto skipBytes = partSize * (i - 1);
        auto size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
        std::shared_ptr<std::iostream> content = std::make_shared<std::fstream>(fileToUpload, std::ios::in|std::ios::binary);
        content->seekg(skipBytes, std::ios::beg);

        UploadPartRequest uploadPartRequest(BucketName, ObjectName, content);
        uploadPartRequest.setContentLength(size);
                uploadPartRequest.setUploadId(uploadId);
        uploadPartRequest.setPartNumber(i);
        auto uploadPartOutcome = client.UploadPart(uploadPartRequest);
        if (uploadPartOutcome.isSuccess()) {
            Part part(i, uploadPartOutcome.result().ETag());
            partETagList.push_back(part);
        }
        else {
            std::cout << "uploadPart fail" <<
            ",code:" << uploadPartOutcome.error().Code() <<
            ",message:" << uploadPartOutcome.error().Message() <<
            ",requestId:" << uploadPartOutcome.error().RequestId() << std::endl;
        }

    }

    /* マルチパートアップロードタスクを完了します。 */
    /* マルチパートアップロードタスクが完了したら、すべての有効な PartETag を指定する必要があります。OSS は PartETag を受信した後、すべてのパートを 1 つずつ検証します。パート検証が成功した後、OSS はこれらのパートを完全なオブジェクトに結合します。 */
    CompleteMultipartUploadRequest request(BucketName, ObjectName);
    request.setUploadId(uploadId);
    request.setPartList(partETagList);
    /* (オプション) オブジェクトの ACL を指定します。 */
    //request.setAcl(CannedAccessControlList::Private);

    auto outcome = client.CompleteMultipartUpload(request);

    if (!outcome.isSuccess()) {
        /* 例外を処理します。 */
        std::cout << "CompleteMultipartUpload fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /* ネットワークリソースなどのリソースを解放します。 */
    ShutdownSdk();
    return 0;
}

C

次のサンプルコードは、OSS SDK for C を使用してマルチパートアップロードを実装する方法の例を示しています。

#include "oss_api.h"
#include "aos_http_io.h"
#include <sys/stat.h>
/* バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。 */
const char *endpoint = "yourEndpoint";

/* バケットの名前を指定します。例: examplebucket。 */
const char *bucket_name = "examplebucket";
/* オブジェクトのフルパスを指定します。フルパスにバケット名を含めないでください。例: exampledir/exampleobject.txt。 */
const char *object_name = "exampledir/exampleobject.txt";
/* ローカルファイルのフルパスを指定します。 */
const char *local_filename = "yourLocalFilename";
/* バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。 */
const char *region = "yourRegion";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* char* 文字列を使用して aos_string_t タイプのデータを初期化します。 */
    aos_str_set(&options->config->endpoint, endpoint);
    /* 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が構成されていることを確認してください。 */    
    aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
    aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
    // 2 つの追加パラメーターを指定します。
    aos_str_set(&options->config->region, region);
    options->config->signature_version = 4;
    /* CNAME を使用して OSS にアクセスするかどうかを指定します。値 0 は、CNAME が使用されていないことを示します。 */
    options->config->is_cname = 0;
    /* タイムアウト期間などのネットワークパラメーターを構成します。 */
    options->ctl = aos_http_controller_create(options->pool, 0);
}
int64_t get_file_size(const char *file_path)
{
    int64_t filesize = -1;
    struct stat statbuff;
    if(stat(file_path, &statbuff) < 0){
        return filesize;
    } else {
        filesize = statbuff.st_size;
    }
    return filesize;
}
int main(int argc, char *argv[])
{
    /* main() で aos_http_io_initialize メソッドを呼び出して、ネットワークリソースやメモリリソースなどのグローバルリソースを初期化します。 */
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }
    /* メモリを管理するためのメモリプールを作成します。aos_pool_t は apr_pool_t と同等です。メモリプールを作成するために使用されるコードは、APR ライブラリに含まれています。 */
    aos_pool_t *pool;
    /* メモリプールを作成します。2 番目のパラメーターの値は NULL です。この値は、プールが他のメモリプールを継承しないことを示します。 */
    aos_pool_create(&pool, NULL);
    /* オプションを作成して初期化します。このパラメーターには、エンドポイント、access_key_id、access_key_secret、is_cname、curl などのグローバル構成情報が含まれています。 */
    oss_request_options_t *oss_client_options;
    /* メモリプールのメモリリソースをオプションに割り当てます。 */
    oss_client_options = oss_request_options_create(pool);
    /* oss_client_options を初期化します。 */
    init_options(oss_client_options);
    /* パラメーターを初期化します。 */
    aos_string_t bucket;
    aos_string_t object;
    oss_upload_file_t *upload_file = NULL;
    aos_string_t upload_id;   
    aos_table_t *headers = NULL;
    aos_table_t *complete_headers = NULL;
    aos_table_t *resp_headers = NULL;
    aos_status_t *resp_status = NULL; 
    aos_str_set(&bucket, bucket_name);
    aos_str_set(&object, object_name);
    aos_str_null(&upload_id);
    headers = aos_table_make(pool, 1);
    complete_headers = aos_table_make(pool, 1);
    int part_num = 1;
    /* マルチパートアップロードタスクを開始し、アップロード ID を取得します。 */
    resp_status = oss_init_multipart_upload(oss_client_options, &bucket, &object, &upload_id, headers, &resp_headers);
    /* マルチパートアップロードタスクが初期化されているかどうかを確認します。 */
    if (aos_status_is_ok(resp_status)) {
        printf("マルチパートアップロードの初期化に成功しました、upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    } else {
        printf("マルチパートアップロードの初期化に失敗しました、upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    }
    /* パートをアップロードします。 */
    int64_t file_length = 0;
    int64_t pos = 0;
    aos_list_t complete_part_list;
       oss_complete_part_content_t* complete_content = NULL;
    char* part_num_str = NULL;
    char* etag = NULL;
    aos_list_init(&complete_part_list);
    file_length = get_file_size(local_filename);
    while(pos < file_length) {
        upload_file = oss_create_upload_file(pool);
        aos_str_set(&upload_file->filename, local_filename);
        upload_file->file_pos = pos;
        pos += 100 * 1024;
        upload_file->file_last = pos < file_length ? pos : file_length;
        resp_status = oss_upload_part_from_file(oss_client_options, &bucket, &object, &upload_id, part_num++, upload_file, &resp_headers);

        /* パート番号と ETag を保存します。 */
        complete_content = oss_create_complete_part_content(pool);
        part_num_str = apr_psprintf(pool, "%d", part_num-1);
        aos_str_set(&complete_content->part_number, part_num_str);
        etag = apr_pstrdup(pool,
        (char*)apr_table_get(resp_headers, "ETag"));
        aos_str_set(&complete_content->etag, etag);
        aos_list_add_tail(&complete_content->node, &complete_part_list);

        if (aos_status_is_ok(resp_status)) {
            printf("ファイルからのマルチパートアップロードパートに成功しました\n");
        } else {
            printf("ファイルからのマルチパートアップロードパートに失敗しました\n");
        }
    }

    /* マルチパートアップロードタスクを完了します。 */
    resp_status = oss_complete_multipart_upload(oss_client_options, &bucket, &object, &upload_id,
            &complete_part_list, complete_headers, &resp_headers);
    /* マルチパートアップロードタスクが完了したかどうかを確認します。 */
    if (aos_status_is_ok(resp_status)) {
        printf("ファイルからのマルチパートアップロードの完了に成功しました、upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    } else {
        printf("ファイルからのマルチパートアップロードの完了に失敗しました\n");
    }
    /* メモリプールを解放します。この操作は、リクエストに割り当てられたメモリリソースを解放します。 */
    aos_pool_destroy(pool);
    /* 割り当てられたグローバルリソースを解放します。 */
    aos_http_io_deinitialize();
    return 0;
}

API 操作

ビジネスで高度なカスタマイズが必要な場合は、RESTful API を直接呼び出すことができます。RESTful API を直接呼び出すには、コードに署名計算を含める必要があります。

  • マルチパートアップロード タスクを開始するために呼び出すことができる API 操作については、「InitiateMultipartUpload」をご参照ください。

  • パーツをアップロードするために呼び出すことができる API 操作については、「UploadPart」をご参照ください。

  • 既存のオブジェクトからデータをコピーしてパートをアップロードするために呼び出すことができる API 操作については、「UploadPartCopy」をご参照ください。

  • マルチパートアップロード タスクを完了するために呼び出すことができる API 操作については、「CompleteMultipartUpload」をご参照ください。

  • マルチパートアップロード タスクをキャンセルし、タスクで生成されたパーツを削除するために呼び出すことができる API 操作については、「AbortMultipartUpload」をご参照ください。

  • 詳細については、「進行中のマルチパートアップロードタスクをすべてリストするために呼び出すことができる API 操作」をご参照ください。

  • アップロードされたすべてのパーツをリストするために呼び出すことができる API 操作については、「ListParts」をご参照ください。

権限

デフォルトでは、Alibaba Cloud アカウントはアカウント内のリソースに対するフルアクセス権限を持っています。Alibaba Cloud アカウントの Resource Access Management (RAM) ユーザーまたはロールは、アカウント内のリソースに対する権限を持っていません。RAM ユーザーまたはロールを使用して Alibaba Cloud アカウント内のリソースを管理するには、必要な権限を RAM ユーザーまたはロールに付与する必要があります。詳細については、「RAM ポリシー」および「バケットポリシー」をご参照ください。

API

アクション

説明

InitiateMultipartUpload

oss:PutObject

マルチパートアップロードタスクを初期化します。

oss:PutObjectTagging

マルチパートアップロードタスクの初期化時に、x-oss-tagging ヘッダーを使用してオブジェクトのタグを指定します。

kms:Decrypt

マルチパートアップロードタスクの初期化時に、x-oss-server-side-encryption ヘッダーを使用して Key Management Service (KMS) をパートのサーバー側暗号化方式として指定します。

UploadPart

oss:PutObject

パートをアップロードします。

UploadPartCopy

oss:GetObject

既存のオブジェクトからデータをコピーしてパートをアップロードするときに、ソースオブジェクトのデータを読み取ります。

oss:GetObjectVersion

既存のオブジェクトからデータをコピーしてパートをアップロードするときに、ソースオブジェクトのバージョン ID を読み取ります。

oss:PutObject

既存のオブジェクトからデータをコピーしてパートをアップロードするときに、データをデスティネーションオブジェクトに書き込みます。

CompleteMultipartUpload

oss:PutObject

パートをオブジェクトに結合します。

oss:PutObjectTagging

パートをオブジェクトに結合するときに、x-oss-tagging ヘッダーを使用してオブジェクトのタグを指定します。

AbortMultipartUpload

oss:AbortMultipartUpload

マルチパートアップロードタスクをキャンセルし、アップロードされたパートを削除します。

ListMultipartUploads

oss:ListMultipartUploads

開始されたが未完了またはキャンセルされたタスクを含む、進行中のすべてのマルチパートアップロードタスクを一覧表示します。

ListParts

oss:ListParts

アップロード ID を使用してアップロードされたすべてのパートを一覧表示します。

課金

マルチパートアップロードを使用してローカルファイルを OSS にアップロードすると、料金が発生します。課金対象項目と料金の詳細については、「OSS 料金」をご参照ください。

API

課金項目

説明

InitiateMultipartUpload

PUT リクエスト

成功したリクエストの数に基づいてリクエスト料金が課金されます。

UploadPart

PUT リクエスト

成功したリクエストの数に基づいてリクエスト料金が課金されます。

ストレージ

パートのストレージタイプ、サイズ、および期間に基づいてストレージ料金が課金されます。オブジェクトのパートのストレージタイプは、オブジェクトのストレージタイプと同じです。ただし、パートには最小課金サイズがありません。パートのサイズが 64 KB 未満の場合でも、パートのストレージコストは実際のサイズに基づいて計算されます。パートがアクセスされたかどうかに関係なく、パートに対して操作が実行されたかどうかに関係なく、パートを OSS にアップロードした後、パートが削除されるかオブジェクトに結合されるまで、ストレージ料金が課金されます。

UploadPartCopy

PUT リクエスト

成功したリクエストの数に基づいてリクエスト料金が課金されます。

CompleteMultipartUpload

PUT リクエスト

成功したリクエストの数に基づいてリクエスト料金が課金されます。

ストレージ

オブジェクトのストレージタイプ、サイズ、および期間に基づいてストレージ料金が課金されます。OSS 内のパートをオブジェクトに結合し、オブジェクトを OSS に格納した後、オブジェクトがアクセスされたかどうかに関係なく、オブジェクトに対して操作が実行されたかどうかに関係なく、ストレージ料金が課金されます。

AbortMultipartUpload

PUT リクエスト

成功したリクエストの数に基づいてリクエスト料金が課金されます。

重要
  • 中国本土のリージョンでは、ライフサイクルルールに基づいて IA、アーカイブ、またはコールドアーカイブパートが削除されると、標準パートが削除されたときの PUT リクエスト料金と比較して、より高い PUT リクエスト料金が課金されます。ライフサイクルルールを使用してディープコールドアーカイブパートを削除する場合、PUT リクエスト料金は課金されません。

  • 中国 (香港) リージョンおよび中国本土以外のリージョンでは、ライフサイクルルールを使用して任意のストレージタイプのパートを削除する場合、PUT リクエスト料金は課金されません。

ListMultipartUploads

PUT リクエスト

成功したリクエストの数に基づいてリクエスト料金が課金されます。

ListParts

PUT リクエスト

成功したリクエストの数に基づいてリクエスト料金が課金されます。

制限

制限

説明

オブジェクトのサイズ

最大 48.8 TB。

パートの数

1 から 10000。

パートのサイズ

100 KB から 5 GB。最後のパートのサイズは 100 KB 未満にすることができます。

1 つの ListParts リクエストで返されるパートの最大数

1,000

1 つの ListMultipartUploads リクエストで返されるマルチパートアップロードタスクの最大数

1,000

よくある質問

マルチパートアップロードを使用してディレクトリをアップロードできますか?

いいえ。マルチパートアップロードを使用してディレクトリをアップロードすることはできません。

多数のオブジェクトをアップロードするときに、アップロードパフォーマンスを最適化するにはどうすればよいですか?

タイムスタンプや文字など、名前が連続したプレフィックスを含む多数のオブジェクトをアップロードする場合、複数のオブジェクトインデックスが 1 つのパーティションに格納される可能性があります。オブジェクトをクエリするために多数のリクエストが送信されると、レイテンシが増加します。名前が連続したプレフィックスを含む多数のオブジェクトをアップロードしないことをお勧めします。詳細については、「OSS パフォーマンスのベストプラクティス」をご参照ください。

ストレージタイプがディープコールドアーカイブであるオブジェクトの PUT リクエスト料金が高額になるのを防ぐにはどうすればよいですか?

多数のオブジェクトをアップロードし、オブジェクトのストレージタイプをディープコールドアーカイブに設定する場合、高額な PUT リクエスト料金 が課金されます。オブジェクトをアップロードするときにオブジェクトのストレージタイプを標準に設定し、ライフサイクルルール を構成して標準オブジェクトのストレージタイプをディープコールドアーカイブに変換することをお勧めします。これにより、PUT リクエスト料金が削減されます。

オブジェクトが誤って上書きされるのを防ぐにはどうすればよいですか?

OSS 内の既存のオブジェクトと同じ名前のオブジェクトをアップロードすると、既存のオブジェクトはアップロードされたオブジェクトによって上書きされます。オブジェクトが予期せず上書きされるのを防ぐには、次のいずれかの方法を使用できます。

  • バージョニングを有効にする: バケットのバージョニングを有効にすると、上書きされたオブジェクトは以前のバージョンとして保存されます。いつでもオブジェクトを以前のバージョンに復元できます。詳細については、「バージョニング」をご参照ください。

  • リクエストに同じ名前のオブジェクトが上書きされるのを防ぐために使用されるヘッダーを含める: アップロードリクエストに x-oss-forbid-overwrite ヘッダーを含め、ヘッダーを true に設定します。このようにして、既存のオブジェクトと同じ名前のオブジェクトがアップロードされると、アップロードは失敗し、FileAlreadyExists エラーが返されます。詳細については、「InitiateMultipartUpload」をご参照ください。

パートを削除するにはどうすればよいですか?

マルチパートアップロードタスクが中断され、AbortMultipartUpload 操作が呼び出されない場合、タスクによってアップロードされたパートは指定されたバケットに格納されます。パートが不要になった場合は、次のいずれかの方法を使用してパートを削除し、不要なストレージコストが発生しないようにすることができます。

パートを一覧表示するにはどうすればよいですか?

  • 特定のアップロード ID を使用してアップロードされたパーツをリストする場合は、ListParts 操作を呼び出すことができます。詳細については、「ListParts」をご参照ください。

  • 開始済みですが、未完了またはキャンセルされたマルチパートアップロード タスクを一覧表示する場合は、ListMultipartUploads オペレーションを呼び出すことができます。詳細については、「ListMultipartUploads」をご参照ください。

マルチパートアップロードを使用して、暗号化および圧縮されたローカルファイルを OSS にアップロードできますか?

はい。マルチパートアップロードを使用して、暗号化および圧縮されたローカルファイルを OSS にアップロードできます。

マルチパートアップロードタスクが中断された後、パートを再アップロードすると、アップロードされたパートは上書きされますか?

マルチパートアップロードタスクが中断された後、元のアップロード ID を使用してすべてのパートを再アップロードすると、同じ名前のアップロードされたパートは上書きされます。新しいアップロード ID を使用してすべてのパートを再アップロードすると、元のアップロード ID を持つアップロードされたパートは保持されます。

マルチパートアップロードのアップロード ID とは何ですか?

アップロード ID は、マルチパートアップロードタスクを一意に識別します。パート番号は、同じアップロード ID を共有するパートの相対位置を識別します。

マルチパートアップロードタスク中にアップロード ID はどれくらい有効ですか?

アップロード ID は、マルチパートアップロードプロセス中に有効です。マルチパートアップロードタスクが完了またはキャンセルされると、アップロード ID は無効になります。別のマルチパートアップロードタスクを実行する場合は、マルチパートアップロードタスクを再起動して新しいアップロード ID を生成する必要があります。

OSS は自動的にパートを結合しますか?

いいえ。OSS は自動的にパートを結合しません。CompleteMultipartUpload 操作を呼び出して、パートを手動で完全なオブジェクトに結合する必要があります。