はじめに
ファイルアップロード機能、「とりあえず<input type="file">を置いて終わり」にしていませんか。実際にはドラッグ&ドロップ対応、進捗表示、複数ファイル選択、通信が切れたときの再開処理など、まともに作り込もうとすると意外と工数がかかる領域です。しかもGoogle DriveやWebカメラからのアップロードまで求められると、自前実装はあっという間に破綻してしまいます。
Uppyは、こうしたファイルアップロードUIの面倒な部分をまとめて肩代わりしてくれるJavaScriptライブラリです。本記事では、Uppyの特徴からインストール、実際に手を動かせるコード例までを紹介します。
Uppyとは
Uppyは、Transloaditチームが開発しているオープンソース(MITライセンス)のモジュール型ファイルアップローダーです。GitHub上で3万を超えるスターを獲得しており、React・Vue・Svelte・Angularといった主要フレームワークへの公式対応も進んでいる、活発に開発が続くプロジェクトです。
コアとなる@uppy/coreに、UIを提供する@uppy/dashboard、アップロード先ごとのプラグイン(@uppy/tusや@uppy/aws-s3など)を組み合わせて使う設計になっており、必要な機能だけを取捨選択できるのが大きな強みです。
主な特徴
- プラグインベースの設計 - コアは最小限に保たれており、UI・アップロード先・取得元をプラグインとして自由に組み合わせられる
- レジューマブルアップロード - tusプロトコルに対応しており、通信が途切れても続きから再開できる
- 多様なファイル取得元 - ローカルディスクだけでなく、Google Drive、Dropbox、Webカメラなどからの取得にも対応
- フレームワーク対応の柔軟さ - React・Vue・Svelte向けにコンポーネント、ヘッドレスAPI、フックの3通りの使い方が用意されている
インストール
npmまたはyarnで、コアとDashboard、アップロード先プラグイン(ここではtusを例にします)をまとめてインストールします。
npm install @uppy/core @uppy/dashboard @uppy/tus
DashboardのUIにはスタイルシートも必要です。
npm install @uppy/core @uppy/dashboard @uppy/tus @uppy/webcam
CSSはJavaScript側でインポートするか、CDN経由で読み込みます。
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
基本的な使い方
まずは最小構成として、Dashboard UIを表示し、tusサーバーへアップロードする例です。
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import Tus from '@uppy/tus';
const uppy = new Uppy({
restrictions: {
maxFileSize: 10 * 1024 * 1024, // 10MB
maxNumberOfFiles: 5,
allowedFileTypes: ['image/*', 'application/pdf'],
},
})
.use(Dashboard, {
inline: true,
target: '#uppy-dashboard',
height: 400,
})
.use(Tus, {
endpoint: 'https://tusd.example.com/files/',
});
uppy.on('complete', (result) => {
console.log('アップロード成功:', result.successful);
console.log('アップロード失敗:', result.failed);
});
HTML側にはDashboardを描画するコンテナを用意するだけです。
<div id="uppy-dashboard"></div>
restrictionsでファイルサイズや形式、点数の上限を設定できるため、バリデーションを個別に実装する手間も省けます。
実践的なユースケース
React環境では、公式が提供する@uppy/reactを使うことで、Dashboardをコンポーネントとして扱えます。プロフィール画像のアップロードフォームを例に見てみましょう。
import { useState } from 'react';
import Uppy from '@uppy/core';
import { Dashboard } from '@uppy/react';
import Tus from '@uppy/tus';
function ProfileImageUploader() {
const [uppy] = useState(() =>
new Uppy({
restrictions: {
maxNumberOfFiles: 1,
allowedFileTypes: ['image/*'],
},
}).use(Tus, {
endpoint: '/api/uploads', // 自前のバックエンドのtusエンドポイント
})
);
uppy.on('complete', (result) => {
const uploadedFile = result.successful[0];
if (uploadedFile) {
console.log('アップロード完了:', uploadedFile.uploadURL);
}
});
return (
<Dashboard
uppy={uppy}
proudlyDisplayPoweredByUppy={false}
height={300}
note="JPEG・PNG形式、1枚のみアップロード可能です"
/>
);
}
export default ProfileImageUploader;
外出先での通信環境を想定するアプリであれば、Golden Retrieverプラグインを追加しておくと、ブラウザがクラッシュしたりタブを誤って閉じたりしても、アップロード状態をローカルに保持して復旧できます。
import GoldenRetriever from '@uppy/golden-retriever';
uppy.use(GoldenRetriever, { serviceWorker: false });
イベント検収管理システムの提出書類アップロードや、ECサイトの商品画像登録フォームなど、「ユーザーがアップロードを中断されても困らない」ことが求められる場面で特に効果を発揮します。
まとめ
Uppyを使うことで、ドラッグ&ドロップ対応、進捗表示、複数ファイル取得元、通信断からの再開といった、ファイルアップロードUIにまつわる面倒な実装をまとめて任せられることが分かりました。プラグイン構成のおかげで、必要な機能だけを選んで軽量に導入できるのも実用的なポイントです。
まずは@uppy/coreと@uppy/dashboardだけの最小構成で動かしてみて、そこからtusやAWS S3、Webカメラといったプラグインを少しずつ追加していくのがおすすめです。公式ドキュメントには各プラグインのオプションが詳しく載っているので、自分のアプリに合わせてカスタマイズしてみてください。