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

Object Storage Service:フラグメントアップロード(Harmony SDK)

最終更新日:Mar 20, 2026

OSS へ大規模ファイルを信頼性高くアップロードするには、フラグメントアップロードをご利用ください。ファイル全体を単一のリクエストで送信する代わりに、ファイルを複数のパート(フラグメント)に分割し、各パートを並列でアップロードした後、それらを結合して 1 つの完全なオブジェクトとして作成します。この手法により、スループットが向上し、ネットワーク切断からの迅速な回復が可能となり、中断されたアップロードを最初からやり直さずに再開できます。

前提条件

開始する前に、以下の条件を満たしていることを確認してください。

仕組み

フラグメントアップロードは、以下の 3 つのステップで実行されます。

  1. 初期化client.initiateMultipartUpload を呼び出します。OSS は、このアップロードセッションを一意に識別するグローバルにユニークなアップロード ID を返します。

  2. パートのアップロード — 各パートをパート番号で識別し、client.uploadPart を呼び出します。パートは並列でアップロード可能です。

  3. 完了client.completeMultipartUpload を呼び出します。OSS は、パート番号の順序に従ってパートをアセンブルし、1 つの完全なオブジェクトを作成します。

パート番号の動作:

  • パート番号は、各パートが最終オブジェクト内で占める位置を識別します。

  • 既存のパート番号で新しいパートをアップロードすると、既存のパートが上書きされます。

  • OSS は、受信した各パートの MD5 ハッシュ値を ETag ヘッダーで返します。

  • アップロードされたデータの MD5 ハッシュ値が SDK によって計算されたハッシュ値と一致しない場合、OSS は InvalidDigest エラーを返します。

ファイルをパート単位でアップロード

以下の例では、ローカルファイルを 10 MB 単位のパートに分割し、Promise.all を使用して同時並列でアップロードします。

import Client, { FilePath, RequestError, THarmonyEmptyBodyApiRes } from '@aliyun/oss';
import { fileIo as fs } from '@kit.CoreFileKit';

// OSS クライアントインスタンスを作成します。
const client = new Client({
  // STS 一時アクセス認証情報から取得した AccessKey ID に置き換えます。
  accessKeyId: 'yourAccessKeyId',
  // STS 一時アクセス認証情報から取得した AccessKey Secret に置き換えます。
  accessKeySecret: 'yourAccessKeySecret',
  // STS 一時アクセス認証情報から取得したセキュリティトークンに置き換えます。
  securityToken: 'yourSecurityToken',
  // バケットが配置されているリージョンを指定します。たとえば、バケットが
  // 中国 (杭州) リージョンにある場合は、region を oss-cn-hangzhou に設定します。
  region: 'oss-cn-hangzhou',
});

const bucket = 'yourBucketName';   // 実際のバケット名に置き換えます。
const key = 'yourObjectName';      // 実際のオブジェクト名に置き換えます。

const multipartUpload = async () => {
  try {
    // ステップ 1:フラグメントアップロードを初期化し、アップロード ID を取得します。
    const initRes = await client.initiateMultipartUpload({ bucket, key });
    const uploadId = initRes.data.uploadId;

    // ステップ 2:ファイルをパートに分割し、並列でアップロードします。
    const filePath = new FilePath('yourFilePath'); // 実際のローカルファイルパスに置き換えます。
    const fileStat = await fs.stat(filePath.filePath);

    const chunkSize = 1024 * 1024 * 10; // 各パートのサイズ:10 MB。
    const totalParts = Math.ceil(fileStat.size / chunkSize);

    const waitList: Promise<THarmonyEmptyBodyApiRes>[] = [];

    for (let partNumber = 1; partNumber <= totalParts; partNumber++) {
      const offset = (partNumber - 1) * chunkSize;

      const uploadPromise = client.uploadPart({
        bucket,
        key,
        uploadId,
        partNumber,
        data: filePath,
        length: Math.min(chunkSize, fileStat.size - offset), // 現在のパートのサイズ。
        offset,                                               // 現在のパートの開始オフセット。
      });

      waitList.push(uploadPromise);
    }

    // 全パートのアップロード完了を待機します。
    await Promise.all(waitList);

    // ステップ 3:フラグメントアップロードを完了します。
    const completeRes = await client.completeMultipartUpload({
      bucket,
      key,
      uploadId,
      completeAll: true, // アップロード済みのすべてのパートを自動的にアセンブルします。
    });

    console.log(JSON.stringify(completeRes));
  } catch (err) {
    if (err instanceof RequestError) {
      console.log('code: ', err.code);
      console.log('message: ', err.message);
      console.log('requestId: ', err.requestId);
      console.log('status: ', err.status);
      console.log('ec: ', err.ec);
    } else {
      console.log('unknown error: ', err);
    }
  }
};

multipartUpload();

主なパラメーター:

パラメーター説明
uploadIdinitiateMultipartUpload から返される一意の識別子です。以降のすべての uploadPart および completeMultipartUpload の呼び出しに渡す必要があります。
partNumber各パートの連続する番号(1 から開始)。最終オブジェクト内でのパートの位置を決定します。
offsetソースファイル内のこのパートの開始位置(バイト単位のオフセット)。
lengthこのパートのサイズ(バイト単位)。最後のパートは chunkSize より小さくなる場合があります。
completeAlltrue を指定すると、OSS は明示的なパートリストを必要とせず、アップロード済みのすべてのパートを自動的にアセンブルします。

その他の操作

フラグメントアップロードの中止

進行中のアップロードをキャンセルし、アップロード済みのパートが使用していたストレージを解放するには、client.abortMultipartUpload を呼び出します。

import Client, { RequestError } from '@aliyun/oss';

const client = new Client({
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  securityToken: 'yourSecurityToken',
  region: 'oss-cn-hangzhou',
});

const bucket = 'yourBucketName';
const key = 'yourObjectName';

const abortMultipartUpload = async () => {
  try {
    const res = await client.abortMultipartUpload({
      bucket,
      key,
      // initiateMultipartUpload から返されたアップロード ID、または listMultipartUploads で取得したアップロード ID。
      uploadId: 'yourUploadId',
    });

    console.log(JSON.stringify(res));
  } catch (err) {
    if (err instanceof RequestError) {
      console.log('code: ', err.code);
      console.log('message: ', err.message);
      console.log('requestId: ', err.requestId);
      console.log('status: ', err.status);
      console.log('ec: ', err.ec);
    } else {
      console.log('unknown error: ', err);
    }
  }
};

abortMultipartUpload();

アップロード済みパートの一覧表示

指定されたアップロード ID について、すでにアップロード済みのパートを取得するには、client.listParts を呼び出します。アップロードの進捗状況の確認や、中断されたアップロードの再開にご利用ください。

import Client, { RequestError } from '@aliyun/oss';

const client = new Client({
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  securityToken: 'yourSecurityToken',
  region: 'oss-cn-hangzhou',
});

const bucket = 'yourBucketName';
const key = 'yourObjectName';

const listParts = async () => {
  try {
    const res = await client.listParts({
      bucket,
      key,
      // initiateMultipartUpload から返されたアップロード ID、または listMultipartUploads で取得したアップロード ID。
      uploadId: 'yourUploadId',
    });

    console.log(JSON.stringify(res));
  } catch (err) {
    if (err instanceof RequestError) {
      console.log('code: ', err.code);
      console.log('message: ', err.message);
      console.log('requestId: ', err.requestId);
      console.log('status: ', err.status);
      console.log('ec: ', err.ec);
    } else {
      console.log('unknown error: ', err);
    }
  }
};

listParts();

進行中のフラグメントアップロードの一覧表示

OSS バケット内で初期化済みだが、まだ完了も中止もされていないアップロードをすべて一覧表示するには、client.listMultipartUploads を呼び出します。未完了のアップロードの監査や、再開・中止対象のアップロード ID の特定に役立ちます。

import Client, { RequestError } from '@aliyun/oss';

const client = new Client({
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  securityToken: 'yourSecurityToken',
  region: 'oss-cn-hangzhou',
});

const bucket = 'yourBucketName';

const listMultipartUploads = async () => {
  try {
    const res = await client.listMultipartUploads({ bucket });

    console.log(JSON.stringify(res));
  } catch (err) {
    if (err instanceof RequestError) {
      console.log('code: ', err.code);
      console.log('message: ', err.message);
      console.log('requestId: ', err.requestId);
      console.log('status: ', err.status);
      console.log('ec: ', err.ec);
    } else {
      console.log('unknown error: ', err);
    }
  }
};

listMultipartUploads();

中断されたアップロードの再開

HarmonyOS 上では、アプリが一時停止されたり、ネットワークが途中で切断されたりする可能性があります。ただし、アップロード ID は初期化時に返され、OSS 内で永続的に保持されるため、完了済みのパートを再アップロードすることなく再開できます。

  1. initiateMultipartUpload から返された uploadId を、永続ストレージ(たとえばローカルファイルやデータベースなど)に保存します。

  2. アップロードが中断された場合、保存済みの uploadId を使用して client.listParts を呼び出し、すでにアップロード済みのパートを特定します。

  3. client.uploadPart を使用して、不足しているパートのみをアップロードします。

  4. すべてのパートが揃った時点で、client.completeMultipartUpload を呼び出します。

このパターンにより、不要な帯域幅の消費を回避でき、特にモバイルネットワーク環境において重要です。