JavaScriptやReact、Vue.jsなどでドラッグ&ドロップを利用したファイルアップロード機能を実装するのは少し難しいと感じたことはありませんか?ファイルアップロードを簡単に実現するためにJavaScriptにはさまざまなオープンソースのライブラリが公開されています。
本記事ではその中から Uppy というファイルアップローダーライブラリの基本的な使い方を解説します。Uppyを使用すれば、WEBページ上で簡単にファイルをアップロードできるようになります。

Uppyはローカルディスクだけではなく, Google Drive, Dropbop, Instagamなどからファイルを取得することもできます。また、アップロードした画像のプレビュー機能もあり、指定した保存先にファイルのアップロードを行うことができます。

Google Drive等からのファイル取得は動作確認を行なっていないため本文書には設定手順は記述されていません。今後行う予定です。
fukidashi

Uppyとは

UppyはJavaScriptのファイルアップローダーでプラグインを追加することでドラッグ&ドロップ、ファイルのプレビュー機能などを実装することができます。シンプルなAPIなので簡単にアプリケーションに組み込むことができます。現在も頻繁に更新が行わており、ReactのフレームワークであるNext.jsにも対応しています。

Uppyのサイトはhttps://uppy.io/からアクセスすることができます。

プラグインについて

Uppyではプラグインを利用して機能を追加しますがすべてのプラグインの元となるUppy Coreがあります。Core単体ではファイルアップロードをすることはできませんがdebug、log設定やファイルのバリデーションを行うためのオプションを設定する機能が備わっています。

プラグインにはDashboardやFileInput、Progress Barなどがあります。Dashboardプラグインを利用することでドラッグ&ドロップ、アップロードしたファイルのプレビューも行うことができます。FileInputでは通常のinput要素からのファイルアップロードのようにファイル選択を行うとファイル選択画面が表示されローカルファイルのアップロードを行うことができます。Progress Barではファイルアップロードの進捗具合をバーで表示してくれます。これ以外にもファイルアップロードには欲しい機能がプラグインで提供されています。

DashBoardを利用したファイルアップロード

もっともシンプルなコードで高機能なファイルのアップロードを行いたい場合にDashBoardプラグインを利用することができます。ここではUppyの動作確認を行うためにcdnを使います。ローカルのPCにindex.htmlファイルを作成してその中にコードを記述していきます。

ドラッグ&ドロップエリアの表示

以下のコードを記述するだけでファイルをアップロードするためのドラッグ&ドロップエリアがページ上に表示されます。


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link
      href="https://releases.transloadit.com/uppy/v4.8.0/uppy.min.css"
      rel="stylesheet"
    />
  </head>
  <body>
    <div id="uppy"></div>
  </body>
  <script type="module">
    import {
      Uppy,
      Dashboard,
    } from "https://releases.transloadit.com/uppy/v4.8.0/uppy.min.mjs";
    const uppy = new Uppy();
    uppy.use(Dashboard, { target: "#uppy", inline: true });
  </script>
</html>

Dashboardプラグインではオプション設定を行うことができ、targetオプションを使ってDashboradを表示させる要素を指定します。inlineオプションはモーダルウィンドウの設定に関連しておりモーダルウィンドウを使用しない場合はtrueを設定します。今はモーダルウィンドウを使用しないのでtrueに設定しておきます。

Uppyのモーダルウィンドウ機能は後ほど説明します。
fukidashi

上記のコードを記述したファイルをブラウザで開くとドラッグ&ドロップエリアが下記のように表示されます。

ドラッグ&ドロップエリアの表示
ドラッグ&ドロップエリアの表示

「Drop files here」が記述されている四角の領域に画像ファイル(Uppyのサイトからダウンロードしたlogo.svgファイル)をドラッグ&ドロップすると画像のプレビューが表示されます。browseの文字をクリックするとファイルの選択画面が表示され、ドラッグ&ドロップだけではなく通常のファイル選択の機能も実装されています。

画像のプレビュー
画像のプレビュー

下部には「Upload 1 file」のボタンが表示されていますが、サーバへのアップロード処理は何も行なっていないためボタンをクリックをしても何も起こりません。ファイルをアップロードするためにはサーバの設定が必要となります。

また画像ではなくPDFファイルをアップロードした場合には下記のように表示されます。

PDFファイルをアップロードした場合
PDFファイルをDrag&Dropした場合

ここまでの設定でUppyを利用してドラッグ&ドロップ領域を表示させることとファイルをそのエリアにドラッグ&ドロップできることが確認できました。

ファイルのアップロード

ファイルをサーバにアップロードするためには、xhr-uploadプラグインを追加設定する必要があります。またファイルをアップロードするためにはサーバが必要となります。xhr-uploadではオプションを設定することができ、endpointオプションでアップロードを行うサーバのURLを指定します。


import {
  Uppy,
  Dashboard,
  XHRUpload,
} from "https://releases.transloadit.com/uppy/v4.8.0/uppy.min.mjs";
const uppy = new Uppy();
uppy.use(Dashboard, { target: "#uppy", inline: true });
uppy.use(XHRUpload, { endpoint: "http://127.0.0.1:8000/data" });

ファイルの情報だけではなく、任意の値をサーバ側に渡したい場合は、setMetaメソッドを使用することができます。ここではidに111111を設定しファイルと一緒にid情報を渡そうとしています。


import {
  Uppy,
  Dashboard,
  XHRUpload,
} from "https://releases.transloadit.com/uppy/v4.8.0/uppy.min.mjs";
const uppy = new Uppy();
uppy.use(Dashboard, { target: "#uppy", inline: true });
uppy.use(XHRUpload, { endpoint: "http://127.0.0.1:8000/data" });
uppy.setMeta({ id : 111111 });

Uppyからサーバへ送信したファイルの保存等の処理については通常のHTMLのinput type=”file”を使用した時と同じなので、ここでは省略しますが下記のようにアップロードが完了すると”Upload 1file”のボタンが”Complete”に代わります。

アップロード後の画面
アップロード後の画面

ファイルアップロード先のバックエンドのサーバとしてLaravelを使用している場合は送信されてきたファイルの保存には下記の文書が参考になります。

ここまでの設定で、UppyのDashBoardプラグインを利用したファイルのアップロード機能が実装できます。

ファイルアップロード後の処理

アップロード完了後にサーバから戻られる内容の取得方法を確認します。イベントを利用します。エラーが発生した時も実行されるのでアップロードが正常に完了した時と失敗した時で別々の処理を実行させることができます。

completeイベントを使うためにuppy.onを利用します。


uppy.on('complete', (result) => {
  console.log('successful files:', result.successful)
  console.log('failed files:', result.failed)
})

result.successfulの中にはアップロードした情報やステータスコードも含まれています。アップロード完了後にサーバから戻り値を設定している場合は、responseのbodyを確認すればその値を取得することができます。

complete event取得
complete event取得

エラーがなければ、result.failedの中身は空です。

この他にもcomplete以外にもイベント設定を行うことができるので、公式ドキュメントを参考にしてください。

オプション設定

debug設定やファイルサイズ制限等のvalidation(https://uppy.io/docs/uppy/#restrictions)も行うことができます。


    import {
      Uppy,
      Dashboard,
      XHRUpload,
    } from "https://releases.transloadit.com/uppy/v4.8.0/uppy.min.mjs";
    const uppy = new Uppy({ debug: true,restrictions: { allowedFileTypes:['image/png'] } });
    uppy.use(Dashboard, { target: "#uppy", inline: true });

debugはデフォルトではfalseなのでtrueにするとデベロッパーツールのコンソールに詳細ログが表示されます。restrictionsではファイルサイズはアップロードを一度に行えるファイル数やアップロードを行う最小のファイル数の設定も可能ですが上記ではpngファイルのみアップロード可能となる設定を行っています。png以外のファイルをアップロードすると画面にもエラーメッセージが表示されます。

日本語化設定

以前のバージョンで設定した内容なので本記事作成時にバージョン4については日本語のcdnを見つけることができなかったため動作しませんでした。バージョンによって設定方法が変わるので注意が必要です。ローカルにライブラリはインストールした場合にはバージョン4でも日本語設定は問題なく設定可能です。

デフォルトの言語は英語に設定されていますが、日本語に変更することが可能です。日本語について情報が記述されているja_JP.min.jsを読みむ必要があります。言語に関する文書はここに記述されているので参考にしてください。


<script src="https://transloadit.edgly.net/releases/uppy/locales/v1.4.0/ja_JP.min.js"></script> 

日本語化のJavaScriptを設定したら、Dashboradのオプションにもlocaleを追加します。


var uppy = Uppy.Core().
                use(Uppy.Dashboard,{
                  target:'#drag-drop-area',
                  locale:Uppy.locales.ja_JP,
                  inline:true}
                  )

再度アクセスすると日本語に変わっていることが確認できます。

日本語化設定
日本語化設定

モーダルウィンドウ設定

Uppyでは簡単にモーダルウィンドウの機能を追加することが可能です。

クリックボタンでDashboardエリアがモーダルウィンドウとして表示させる設定を行います。

クリックボタンを設置します。idにはuppy-select-filesを設定します。


<div id="drag-drop-area"></div>
<button id="uppy-select-files">click</button>

inlineオプションはデフォルトではfalseのため、モーダルウィンドウを使用する際は削除します。inlineオプションをtrueにするとモーダルウィンドウではなく<div id=”drag-drop-area”>にDashboardが表示されます。

モーダルウィンドウの切り替えを行う要素はtriggerオプションによって指定します。デフォルトでは#uppy-select-filesが設定されているので、uppy-select-filesを使っている時は省略可能です。


var uppy = Uppy.Core().
                use(Uppy.Dashboard,{
                  target:'#drag-drop-area',
                  trigger:'#uppy-select-files',
                  locale:Uppy.locales.ja_JP}
                  )
クリックボタンの設置
クリックボタンの設置

ボタンをクリックするとモーダルウィンドウが表示されます。右上のXまたはもモーダルウィンドウの外側をクリックするとウィンドウは閉じられます。ファイルをアップロードする方法は、モーダルウィンドウなしと変わりません。

ボタンクリックでモーダルウィンドウ
ボタンクリックでモーダルウィンドウ

他のプラグインの動作確認を行う

Dashboardプラグインを利用すればドラッグ’&ドロップエリアやアップロードのステータス、プレビューもすべて確認を行うことができました。UppyではDashboardプラグイン以外を使ってもファイルのアップロードを行うことができます。

Uppyの理解を深めるために他のプラグインの使い方も確認していきます。

debug機能を使う

Dashboardと違いプラグインによってはユーザには何もメッセージが表示されません。その時はdebugをonにすると行われている内容を確認することができます。

debugオプションはコアモジュールで設定します。


var uppy = Uppy.Core({debug: true})

DragDropプラグインを利用する

DragDropプラグインを使うためにコードを下記のように記述します。


var uppy = Uppy.Core({debug: true}).
                use(Uppy.DragDrop,{
                  target:'#drag-drop-area',
                  locale:Uppy.locales.ja_JP
                })

ドラッグ&ドロップエリアが表示されます。

ドラッグ&ドロップエリアが表示
ドラッグ&ドロップエリアが表示

ファイルをドラッグ&ドロップエリアに入れても画面は何も変化がありません。debugをonにしたのでChromeならデベロッパーツールのConsoleを開いてください。

ファイルをエリアに落とした瞬間に[DragDrop] File were droppedのメッセージが表示され、Drag&Dropが動作していることを確認することができます。

コンソールにログが表示
コンソールにログが表示

ここまでの設定ではまだサーバにはファイルが送信されていません。自動で送信を行わせるためには、コアモジュールにautoProceedオプションを設定してtrueにする必要があります。


var uppy = Uppy.Core({debug: true, autoProceed:true})

Consoleには、追加で下記のアップロードのメッセージが表示されます。


[Uppy] [15:01:49] [XHRUpload] Uploading...
index.js:2 [Uppy] [15:01:49] uploading 1 of 1
index.js:2 [Uppy] [15:01:49] [XHRUpload] cjxvepw5h00013h5hrberli1s started
index.js:2 [Uppy] [15:01:49] [XHRUpload] cjxvepw5h00013h5hrberli1s progress: 4402 / 4402
index.js:2 [Uppy] [15:01:49] [XHRUpload] cjxvepw5h00013h5hrberli1s finished
index.js:2 [Uppy] [15:01:49] [XHRUpload] timer done

ProgressBarプラグインを利用する

ファイルアップロードを視覚的に見るためにProgressBarプラグインを追加します。html側にプログレスバーを表示させる要素が必要になります。<div id=”drag-drop-progress”>を追加し、targetオプションでその要素を指定します。hideAfterFinishオプションをfalseにしているのは、trueにするとファイルアップロード完了後にバーが消えるためです。


var uppy = Uppy.Core({debug:true,autoProceed:true}).
                use(Uppy.DragDrop,{
                  target:'#drag-drop-area',
                  locale:Uppy.locales.ja_JP
                }).
                use(Uppy.ProgressBar, {
                  target: '#drag-drop-progress', 
                  hideAfterFinish: false}).
                use(Uppy.XHRUpload,{
                  endpoint: 'http://127.0.0.1:8000/api/data'
                });

ProgressBar設定後は、ファイルをエリアの下にドロップすると左から右に青い線がプログレスバーとして表示されます。プログレスバーは設定した<div id=”drag-drop-progress”></div>の場所に表示されます。

Progressプラグイン設定後
Progressプラグイン設定後

FileInputプラグインを利用する

DragDropのようなエリアを設定するのではなくファイルを選択させる場合にはFileInputというプラグインがあります。先ほどのコードのDragDropをFileInputに変更します。


var uppy = Uppy.Core({debug:true,autoProceed:true}).
                use(Uppy.FileInput,{
                  target:'#drag-drop-area',
                  locale:Uppy.locales.ja_JP
                }).
                use(Uppy.ProgressBar, {
                  target: '#drag-drop-progress', 
                  hideAfterFinish: false}).
                use(Uppy.XHRUpload,{
                  endpoint: 'http://127.0.0.1:8000/api/data'
                });

ファイルを選択ボタンが表示され、ファイルを選択するとファイルのアップロードが開始され、プログレスバーが左から右へ表示されます。

FileInpuプラグインを利用した場合
FileInpuプラグインを利用した場合

StatusBarプラグインを利用する

ProgressBarよりもより詳細なアップロード状況を知りたい場合には、StatusBarプラグインを使うことができます。

表示に関するオプションでは下記の設定(一部)を行うことができます。

  • hideAfterFinish・・・ファイルのアップロードが完了するとステータスバーを消すか消さないか設定できます
  • showProgressDetails・・・アップロードのバーセント、アップロードしたサイズを確認することができます。
  • hideUploadButton・・・自動アップロードをコアモジュールで設定していない場合falseに設定するとアップロードボタンが表示されます。アップロードボタンを押すとアップロードが開始されます。

ProgressBarよりもオプションが多いので、ファイルのアップロード状況をより詳細に確認することができます。