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

ApsaraVideo VOD:JavaScript SDK を使用したファイルのアップロード

最終更新日:Jul 14, 2026

ApsaraVideo VOD JavaScript SDK (aliyun-vod-upload-sdk) は、ブラウザから ApsaraVideo VOD ストレージに動画および画像ファイルをアップロードします。SDK は、認証情報の取得、マルチパートアップロード、再開可能なアップロード、進捗状況の追跡を処理します。

ブラウザの要件

ブラウザ最小バージョン
Chrome60+
Microsoft Edge79+ (Chromium)
Firefox55+
Safari11+
Android デフォルトブラウザ60+
iOS デフォルトブラウザ11+

クイックスタート

完全に動作するサンプルとして、デモのソースコードをダウンロードできます。

インストール

npm を使用して SDK をインストールします。

npm install aliyun-vod-upload-sdk

SDK は ESM、CJS、UMD ビルドを提供し、すべての最新のバンドラー (Vite、webpack、Rollup、esbuild) をサポートしています。

CDN からのインポート

バンドラーを使用せずに SDK を利用するには、CDN からインポートします。

<script src="https://g.alicdn.com/apsara-media-box/imp-web-vod-upload/2.0.0/vod-upload.umd.js"></script>
<script>
  const { createUploader, UploadError } = window.VodUpload;
</script>

バックエンド API の要件

SDK は Alibaba Cloud OpenAPI を直接呼び出しません。代わりに、getAuth コールバックを介してバックエンドにデリゲートし、アップロード認証情報を取得します。バックエンドは、VOD OpenAPI オペレーションに対応する以下の API を実装する必要があります。

バックエンド API対応する OpenAPI オペレーション応答フィールド
動画アップロード認証情報の作成CreateUploadVideo{ UploadAuth, UploadAddress, VideoId }
動画アップロード認証情報のリフレッシュRefreshUploadVideo{ UploadAuth, UploadAddress, VideoId }
画像アップロード認証情報の作成CreateUploadImage{ UploadAuth, UploadAddress, ImageId }

バックエンドの応答 JSON は、そのまま SDK に渡されます。SDK は Base64 デコードとフィールドマッピングを自動的に処理します。

5行のコードでファイルをアップロード

次の例は、ファイルをアップロードするための最小限のコードを示しています。

import { createUploader } from 'aliyun-vod-upload-sdk';

const uploader = createUploader({
  getAuth: () => fetch('/api/vod/auth').then(r => r.json()),
});

// file は File オブジェクトです。例えば <input type="file"> 要素から取得します
const { videoId } = await uploader.upload(file);

基本機能

動画のアップロード

次の例では、初回の認証情報作成と認証情報のリフレッシュの両方を処理する getAuth コールバックを持つアップローダーを作成します。

import { createUploader } from 'aliyun-vod-upload-sdk';

const uploader = createUploader({
  getAuth: async (ctx) => {
    switch (ctx.kind) {
      case 'create-video':
        return fetch('/api/vod/create-auth', {
          method: 'POST',
          body: JSON.stringify({ fileName: ctx.file.name, ...ctx.meta }),
        }).then(r => r.json());
      case 'refresh-video':
        return fetch(`/api/vod/refresh-auth?videoId=${ctx.videoId}`)
          .then(r => r.json());
    }
  },
});

const result = await uploader.upload(file, {
  meta: { title: 'My Video', cateId: 1000, tags: 'tutorial,example' },
});
console.log('Upload successful, videoId:', result.videoId);

getAuth コールバックは ctx パラメーターを受け取ります。SDK はシナリオに基づいて ctx.kind を自動的に決定します。

  • create-video — 初回アップロード。バックエンドは CreateUploadVideo を呼び出す必要があります。

  • refresh-video — 再開可能なアップロード中の認証情報のリフレッシュ。バックエンドは RefreshUploadVideo を呼び出す必要があります。

  • create-image — 画像のアップロード。バックエンドは CreateUploadImage を呼び出す必要があります。

画像のアップロード

画像のアップロードには、同じ upload() メソッドを使用します。SDK は file.type に基づいてファイルタイプを自動的に検出します (image/* タイプは画像アップロードパスを使用します)。

const uploader = createUploader({
  getAuth: async (ctx) => {
    if (ctx.kind === 'create-image') {
      return fetch('/api/vod/image-auth', {
        method: 'POST',
        body: JSON.stringify({ imageType: 'default' }),
      }).then(r => r.json());
    }
  },
});

const result = await uploader.upload(imageFile);
console.log('Image upload successful, imageId:', result.imageId);

アップロード進捗の追跡

onProgress コールバックを使用して、アップロードの進捗状況を追跡します。

const result = await uploader.upload(file, {
  onProgress: (percent, loaded, total) => {
    // percent: 0..1 (例: 0.5 は 50% を意味します)
    // loaded:  アップロードされたバイト数
    // total:   合計ファイルサイズ (バイト単位)
    progressBar.value = percent;
    console.log(`${(percent * 100).toFixed(1)}% - ${loaded} / ${total}`);
  },
});

アップロードが完了すると、SDK は percent1 になることを保証します。

アップロードのキャンセル

task.abort() メソッドまたは AbortSignal を使用してアップロードをキャンセルできます。

  • 方法 1: task.abort() — 最も簡単なアプローチ

const task = uploader.upload(file);

cancelBtn.onclick = () => task.abort();

try {
  const result = await task;
} catch (e) {
  if (e.name === 'AbortError') {
    console.log('Upload canceled by user');
  }
}
  • 方法 2: AbortSignal — React/Vue コンポーネントのライフサイクルに適しています

const ctrl = new AbortController();
cancelBtn.onclick = () => ctrl.abort();

try {
  const result = await uploader.upload(file, { signal: ctrl.signal });
} catch (e) {
  if (e.name === 'AbortError') {
    console.log('Upload canceled');
  }
}

キャンセル後、チェックポイントは保持されます。次に upload(file) を呼び出すと、ブレークポイントから自動的に再開されます。

再開可能なアップロード

再開可能なアップロードはデフォルトで有効になっており、追加の設定は不要です。この機能は動画のアップロードでのみサポートされています。画像のアップロードでは再開可能なアップロードは使用されません。SDK は自動的に以下を実行します。

  • 完了したパートの進捗を localStorage に保存します。

  • ページのリフレッシュ後に再度 upload(file) が呼び出されると、アップロードが中断された場所から再開します。

  • 同じ file.name + file.size + file.lastModified というルールを使用してチェックポイントを照合します。

// 初回アップロード (ユーザーが進捗 40% でページを閉じる)
await uploader.upload(file);

// ユーザーがページを再度開き、同じファイルを再度アップロードする
// SDK は再アップロードせずに 40% から自動的に再開する
const result = await uploader.upload(file);

再開可能なアップロードを無効にするには、次のようにします。

const uploader = createUploader({
  getAuth: myGetAuth,
  checkpoint: false,  // 再開可能なアップロードを無効にする
});

高度な機能

バッチアップロード

SDK は単一ファイルの upload() API を提供します。バッチアップロードには、標準の JavaScript 非同期プリミティブを使用します。

シリアルアップロード (最も簡単)

for (const file of files) {
  const result = await uploader.upload(file, {
    onProgress: p => updateProgress(file.name, p),
  });
  console.log(`${file.name} complete, videoId: ${result.videoId}`);
}

同時アップロード (高帯域幅で小さなファイル向け)

const results = await Promise.all(
  files.map(f => uploader.upload(f)),
);

(推奨) 同時実行数制限付きアップロード (大きなファイル向け)

import pLimit from 'p-limit';

const limit = pLimit(2); // 同時に最大 2 ファイルをアップロード
const results = await Promise.all(
  files.map(f => limit(() => uploader.upload(f, {
    onProgress: p => updateItemProgress(f, p),
  }))),
);

一時停止と再開

SDK には明示的な一時停止 API はありません。キャンセル + 再開によって一時停止の効果を実現します。

// 一時停止: 現在のアップロードをキャンセル
task.abort();

// 再開: 同じファイルを再アップロードし、チェックポイントから自動的に再開
const result = await uploader.upload(file);

タイムアウトと複数ソースからのキャンセル

AbortSignal.timeout()AbortSignal.any() を使用して、タイムアウトベースおよび組み合わせたキャンセルを実装します。

// 60 秒後に自動キャンセル
await uploader.upload(file, {
  signal: AbortSignal.timeout(60_000),
});

// 複数ソースからのキャンセル: ユーザーによる手動キャンセルまたは 60 秒のタイムアウト
const userCtrl = new AbortController();
await uploader.upload(file, {
  signal: AbortSignal.any([
    userCtrl.signal,
    AbortSignal.timeout(60_000),
  ]),
});

React と Vue の統合

React

React フックの例

import { useEffect, useState, useRef } from 'react';
import { createUploader, UploadError } from 'aliyun-vod-upload-sdk';

function useUploader(getAuth) {
  const uploaderRef = useRef(createUploader({ getAuth }));

  useEffect(() => {
    return () => uploaderRef.current.dispose(); // アンマウント時に解放
  }, []);

  return uploaderRef.current;
}

function UploadButton({ file }) {
  const uploader = useUploader(myGetAuth);
  const [progress, setProgress] = useState(0);

  const handleUpload = () => {
    const ctrl = new AbortController();

    uploader.upload(file, {
      signal: ctrl.signal,
      onProgress: p => setProgress(p),
    }).then(result => {
      console.log('Success', result.videoId);
    }).catch(e => {
      if (e.name !== 'AbortError') {
        console.error('Failed', e);
      }
    });
  };

  return <button onClick={handleUpload}>Upload ({(progress * 100).toFixed(0)}%)</button>;
}

Vue 3

Vue 3 コンポーザブルの例

import { onUnmounted, ref } from 'vue';
import { createUploader } from 'aliyun-vod-upload-sdk';

export function useUploader(getAuth) {
  const uploader = createUploader({ getAuth });
  const progress = ref(0);

  onUnmounted(() => uploader.dispose());

  async function upload(file) {
    return uploader.upload(file, {
      onProgress: p => { progress.value = p; },
    });
  }

  return { upload, progress };
}

API リファレンス

createUploader(config)

Uploader インスタンスを作成します。

import { createUploader } from 'aliyun-vod-upload-sdk';

const uploader = createUploader(config);

UploaderConfig

パラメータータイプ必須デフォルト説明
getAuthGetAuthはい認証情報取得コールバック。詳細については、getAuth コールバックをご参照ください。
retryRetryPolicyいいえ{ count: 3 }OSS マルチパートアップロード失敗時の自動リトライポリシー。
checkpointfalse | { store?: CheckpointStore }いいえlocalStorage再開可能なアップロードの設定。false に設定すると無効になります。{ store } に設定すると、カスタムストアを注入します。
parallelnumberいいえ4同時 OSS パート数。
partSizenumberいいえ1048576 (1 MB)OSS パートサイズ (バイト単位)。
timeoutnumberいいえ60000ネットワークリクエストのタイムアウト (ミリ秒単位)。
cnamestringいいえカスタム OSS ドメイン名。
refreshSTSTokenIntervalnumberいいえ300000 (5 分)STS 認証情報のリフレッシュチェック間隔 (ミリ秒単位)。

RetryPolicy

フィールドタイプデフォルト説明
countnumber3最大リトライ回数。

uploader.upload(file, options?)

単一のファイルをアップロードします。UploadTask を返します。これは Promise<UploadResult> であり、かつ .abort() メソッドを持つオブジェクトです。

const task = uploader.upload(file, options);

UploadOptions

パラメータータイプ説明
metaVodVideoMeta | VodImageMetaメディアメタデータ (タイトル、カテゴリ、タグなど)。
signalAbortSignalWeb 標準のキャンセルシグナル。
onProgress(percent, loaded, total) => void進捗コールバック。percent の値の範囲は 0 から 1 です。
partSizenumberグローバルの partSize を上書きします。
parallelnumberグローバルの parallel を上書きします。

VodVideoMeta (動画メタデータ)

フィールドタイプ説明
titlestring動画のタイトル。
descriptionstring動画の説明。
cateIdnumberカテゴリ ID。
tagsstringタグ。カンマで区切ります。
templateGroupIdstringトランスコーディングテンプレートグループ ID。
storageLocationstringストレージアドレス。
coverUrlstringカバー画像 URL。
workflowIdstringワークフロー ID。
appIdstringアプリケーション ID。
userDataRecordカスタムデータ。

VodImageMeta (画像メタデータ)

フィールドタイプ説明
titlestring画像のタイトル。
descriptionstring画像の説明。
imageType'default' | 'cover' | 'watermark'画像タイプ。
imageExtstring画像ファイルの拡張子。
tagsstringタグ。
cateIdnumberカテゴリ ID。
storageLocationstringストレージアドレス。

UploadResult

フィールドタイプ説明
videoIdstring?動画 ID。動画のアップロード時に返されます。
imageIdstring?画像 ID。画像のアップロード時に返されます。
etagstringOSS ETag。
requestIdstringOSS リクエスト ID。
durationMsnumberアップロード時間 (ミリ秒単位)。
uploadTaskIdstring一意のアップロードタスク ID。テクニカルサポートとのトラブルシューティングに使用できます。

UploadTask

upload() によって返されるオブジェクトは、Promise<UploadResult> であり、かつ .abort() メソッドを持つオブジェクトです。

type UploadTask = Promise<UploadResult> & {
  abort(): void;
};

.abort() メソッドは、チェーンすると失われます。task.then(fn) は通常の Promise を返します。チェーン後もキャンセル機能を保持するには、options.signal を使用します。

uploader.dispose()

リソースを解放します。進行中のすべてのアップロードをキャンセルし、内部状態をクリアします。

uploader.dispose();

この呼び出しの後、uploader インスタンスは再利用できません。メモリリークを防ぐために、React または Vue コンポーネントがアンマウントされるときにこのメソッドを呼び出してください。

getAuth コールバック

type GetAuth = (ctx: AuthContext) => Promise<AuthResult>;

AuthContext

SDK は、アップロードシナリオに基づいて異なる ctx 値を渡します。

ctx.kindトリガーシナリオ追加の ctx フィールド
'create-video'初回の動画アップロードfile, meta?
'refresh-video'再開可能なアップロード中の認証情報のリフレッシュfile, videoId
'create-image'画像のアップロードfile, meta?

AuthResult

バックエンドが OpenAPI 応答から返した生の JSON。SDK はそれを自動的にデコードします。

フィールドタイプ必須説明
UploadAuthstringはいBase64 エンコードされた STS 認証情報。
UploadAddressstringはいBase64 エンコードされた OSS アップロードアドレス。
VideoIdstringcreate-video に必須動画 ID。
ImageIdstringcreate-image に必須画像 ID。
ImageURLstringいいえ画像 URL (パススルー)。

最も簡単な getAuth の実装:

// 統一されたバックエンドルート
createUploader({
  getAuth: ctx => fetch('/api/vod/auth', {
    method: 'POST',
    body: JSON.stringify(ctx),
  }).then(r => r.json()),
});

refresh-video 失敗時の自動フォールバック: 再開可能なアップロード中に認証情報のリフレッシュが失敗した場合、SDK は自動的に create-video にフォールバックしてファイルを再アップロードします。これは呼び出し元に対して完全に透過的です。

エラーハンドリング

UploadError の構造

すべてのアップロードエラーは UploadError インスタンスです (Error を拡張)。

import { UploadError } from 'aliyun-vod-upload-sdk';

class UploadError extends Error {
  readonly code: string;           // 構造化されたエラーコード、例: 'UPLOAD.OSS.ACCESS_DENIED'
  readonly message: string;        // エラーの説明
  readonly suggestion: string;     // 修正提案
  readonly cause?: unknown;        // 元となる根本的なエラー
  readonly uploadTaskId?: string;  // アップロードタスク ID (トラブルシューティング用)
}

ユーザーによるアップロードのキャンセルは UploadError ではありません。これは標準の DOMException (name === 'AbortError') です。

エラーコード

エラーコードのフォーマット: UPLOAD.{layer}.{type}

エラーコード説明推奨される修正
UPLOAD.AUTH.GET_AUTH_FAILEDgetAuth コールバックがエラーをスローしたか、無効な構造を返しました。getAuth コールバックが UploadAuth および UploadAddress フィールドを含む JSON を正しく返すか確認してください。バックエンドサービスが利用可能で、応答フォーマットが正しいことを確認してください。
UPLOAD.OSS.ACCESS_DENIEDOSS 権限エラー (403)。アップロード認証情報 (STS トークン) が有効で期限切れでないか、RAM ポリシーが OSS の書き込み権限を付与しているか確認してください。
UPLOAD.OSS.NO_SUCH_BUCKETバケットが存在しません。アップロードアドレスのバケット名が正しいか確認し、対応するリージョンにバケットが作成されていることを確認してください。
UPLOAD.OSS.NO_SUCH_UPLOADマルチパートアップロードセッションが期限切れになりました。マルチパートアップロードセッションが期限切れになりました (おそらく 24 時間以上経過)。SDK は自動的にファイルを再アップロードします。手動での操作は不要です。
UPLOAD.OSS.UNKNOWN不明な OSS エラー。ブラウザのコンソールで詳細なエラー情報を確認するか、テクニカルサポートにお問い合わせください。
UPLOAD.NETWORK.TIMEOUTリクエストがタイムアウトしました。ブラウザの開発者ツールのネットワークパネルを開き、失敗したリクエストの詳細を確認してください。ネットワーク接続が安定しているか確認するか、タイムアウト設定値を増やしてみてください。
UPLOAD.NETWORK.ERRORネットワーク接続エラー。ブラウザの開発者ツールのネットワークパネルを開き、失敗したリクエストのステータスコードと応答を確認してください。ブラウザが OSS サービスアドレスにアクセスできることを確認してください。プロキシやファイアウォールがリクエストをブロックしていないか確認してください。
UPLOAD.NETWORK.OFFLINEブラウザがオフラインです。ネットワークの状態を確認し、再接続後にアップロードを再試行してください。
UPLOAD.FILE.EMPTYファイルサイズが 0 です。ファイルサイズが 0 です。空のファイルはアップロードできません。正しいファイルが選択されているか確認してください。
UPLOAD.INTERNAL.DISPOSEDUploader インスタンスが破棄されました。createUploader() を再度呼び出して新しいインスタンスを作成してください。

エラーコード定数の使用

(推奨) 文字列リテラルの代わりに ErrorCode 定数を使用します。

import { ErrorCode, UploadError } from 'aliyun-vod-upload-sdk';

try {
  await uploader.upload(file);
} catch (e) {
  if (e instanceof UploadError) {
    switch (e.code) {
      case ErrorCode.AUTH_GET_AUTH_FAILED:
        showToast('認証情報の取得に失敗しました。ページを更新して再試行してください。');
        break;
      case ErrorCode.NETWORK_TIMEOUT:
      case ErrorCode.NETWORK_ERROR:
        showToast('ネットワークエラーです。ネットワークを確認して再試行してください。');
        break;
      case ErrorCode.OSS_ACCESS_DENIED:
        showToast('アップロード権限が不足しています。管理者に連絡してください。');
        break;
      default:
        showToast(`アップロードに失敗しました: ${e.suggestion || e.message}`);
    }
  }
}

トラブルシューティング

UploadError には uploadTaskId が含まれています。これはアップロード全体のグローバルなトレース ID です。この ID を Alibaba Cloud のテクニカルサポートに提供することで、迅速な問題特定が可能になります。

catch (e) {
  if (e instanceof UploadError) {
    // テクニカルサポートチームに送信
    const diagnostic = {
      code: e.code,
      message: e.message,
      uploadTaskId: e.uploadTaskId,
      suggestion: e.suggestion,
    };
    reportToSupport(diagnostic);
  }
}

UploadResult.uploadTaskId は、アップロード成功後のログの相関付けにも使用できます。

const result = await uploader.upload(file);
myLogger.info('Upload successful', { videoId: result.videoId, uploadTaskId: result.uploadTaskId });