blueimp-file-upload、dropzone、filepond、fine-uploader、react-dropzone、uppy はすべて、Web アプリケーションでファイルアップロード機能を実装するための JavaScript ライブラリです。これらのライブラリは、ドラッグ&ドロップ、プログレス表示、サムネイルプレビュー、複数ファイル選択、キャンセル・再開などの共通機能を提供しますが、アーキテクチャ、カスタマイズ性、フレームワークとの統合方法、拡張モデルにおいて大きく異なります。たとえば react-dropzone は React 専用の低レベルフックを提供し、UI は完全に開発者が制御します。一方 uppy や filepond は高機能な UI コンポーネントとモジュール式のプラグインシステムを備え、すぐに使える体験を重視します。
ファイルアップロードは一見単純に見えるが、実際にはドラッグ&ドロップ、プログレス表示、サムネイル生成、キャンセル・再開、バリデーション、クラウド統合など、多くの要件が絡む複雑な機能だ。ここでは、代表的な6つの npm パッケージを、実際のコードと設計思想の観点から比較する。
まず重要な前提として、fine-uploader と blueimp-file-upload は 新規プロジェクトでの使用を避けるべき ライブラリである。
fine-uploader は npm ページ で「This package has been deprecated」の明確な表示があり、GitHub リポジトリも2021年以降更新されていない。blueimp-file-upload も同様に、npm ページ で「This project is no longer actively maintained」と記載されており、jQuery に依存する旧来のアーキテクチャを持つ。以下では、これら2つを参考までに含めるが、主に dropzone、filepond、react-dropzone、uppy の4つに焦点を当てる。
dropzonedropzone は基本的なサムネイル生成をサポートするが、回転補正や EXIF 処理は含まれない。開発者が自前で Canvas API を使って処理を追加する必要がある。
// dropzone: 基本的なサムネイル
new Dropzone('#my-dropzone', {
thumbnail: function(file, dataUrl) {
// dataUrl を img 要素に設定
file.previewElement.querySelector('.dz-image').style.backgroundImage = `url(${dataUrl})`;
}
});
filepondfilepond は画像の EXIF 回転補正、自動向き修正、プレビュー時の圧縮を内蔵しており、開発者の手間を大幅に削減する。
// filepond: 自動で正しい向きのサムネイル
FilePond.create(document.querySelector('input[type="file"]'), {
imagePreviewHeight: 170,
imageCropAspectRatio: '1:1',
imageResizeTargetWidth: 200,
imageResizeTargetHeight: 200
});
react-dropzonereact-dropzone はサムネイル生成を一切提供しない。開発者が URL.createObjectURL() や FileReader を使って自前で実装する必要がある。
// react-dropzone: サムネイルは自分で作る
import { useDropzone } from 'react-dropzone';
function MyDropzone() {
const [preview, setPreview] = useState(null);
const { getRootProps, getInputProps, acceptedFiles } = useDropzone({
onDrop: (files) => setPreview(URL.createObjectURL(files[0]))
});
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
{preview && <img src={preview} alt="preview" style={{ width: 100 }} />}
</div>
);
}
uppyuppy は @uppy/thumbnail-generator プラグインを通じてサムネイルを生成し、EXIF 情報に基づく回転補正も可能だ。
// uppy: プラグインでサムネイル
import Uppy from '@uppy/core';
import ThumbnailGenerator from '@uppy/thumbnail-generator';
const uppy = new Uppy();
uppy.use(ThumbnailGenerator, {
thumbnailWidth: 200,
thumbnailHeight: 200
});
dropzone と filepondこれらは「完成された UI コンポーネント」を提供する。HTML 要素に適用すると、自動でドラッグ領域、プログレスバー、キャンセルボタンなどが描画される。
// dropzone: 完成された UI
Dropzone.options.myDropzone = {
url: '/upload',
maxFilesize: 2,
addRemoveLinks: true
};
// HTML: <form id="my-dropzone" class="dropzone"></form>
// filepond: 同様に完成された UI
FilePond.parse(document.body); // すべての input[type=file] を変換
react-dropzone逆に、react-dropzone は UI は何も提供しない。あくまで「ファイルがドロップされたかどうか」を通知するフックであり、見た目は完全に開発者の責任だ。
// react-dropzone: UI は全部自分で書く
const { getRootProps, getInputProps, isDragActive } = useDropzone();
return (
<div
{...getRootProps()}
style={{
border: '2px dashed #ccc',
padding: 20,
backgroundColor: isDragActive ? '#f0f0f0' : 'white'
}}
>
<input {...getInputProps()} />
{isDragActive ? <p>ここにドロップ!</p> : <p>ファイルをドラッグ or クリック</p>}
</div>
);
uppyuppy は中間的で、@uppy/dashboard のような UI プラグインをオプションで使うことができる。つまり、「必要な UI だけを追加」できる柔軟性がある。
// uppy: 必要に応じて UI を追加
import Dashboard from '@uppy/dashboard';
uppy.use(Dashboard, {
inline: true,
target: '#uppy-container'
});
uppy のモジュール設計uppy はコアとプラグインで構成されており、必要な機能だけを追加できる。
// uppy: プラグインで機能追加
import Uppy from '@uppy/core';
import GoogleDrive from '@uppy/google-drive';
import Webcam from '@uppy/webcam';
import XHRUpload from '@uppy/xhr-upload';
const uppy = new Uppy();
uppy
.use(GoogleDrive, { companionUrl: 'https://companion.example.com' })
.use(Webcam)
.use(XHRUpload, { endpoint: '/upload' });
filepond のプラグインfilepond も同様に、画像編集、圧縮、ファイルサイズ制限などを別パッケージで提供する。
// filepond: プラグイン追加
import FilePondPluginImageExifOrientation from 'filepond-plugin-image-exif-orientation';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
FilePond.registerPlugin(
FilePondPluginImageExifOrientation,
FilePondPluginImagePreview
);
dropzone と react-dropzoneこれらは拡張モデルを持たず、すべてのカスタムロジックをコールバック関数で実装する必要がある。
// dropzone: カスタムロジックはすべてイベントで
Dropzone.options.myDropzone = {
init: function() {
this.on('success', function(file, response) {
// アップロード成功後の処理
});
}
};
react-dropzone: React のライフサイクルと完全に統合され、hooks として自然に使える。ただし UI は自前実装。uppy: @uppy/react で React コンポーネントとして使える。<Dashboard /> や <DragDrop /> といったコンポーネントが提供される。filepond: react-filepond という公式ラッパーがあり、React の props として扱える。dropzone: jQuery に依存しないため React でも使えるが、refs や useEffect で DOM 操作が必要で、やや不自然。// uppy + React
import { Dashboard } from '@uppy/react';
function App() {
return <Dashboard uppy={uppy} />;
}
// filepond + React
import { FilePond } from 'react-filepond';
function App() {
return <FilePond onupdatefiles={setFiles} />;
}
全ライブラリで、アップロード先やリクエスト形式をカスタマイズできるが、その方法は異なる。
dropzonenew Dropzone('#dz', {
url: '/custom-upload',
headers: { 'X-CSRF-Token': '...' },
paramName: 'myFile'
});
filepondFilePond.create(input, {
server: {
process: '/upload',
headers: { 'X-CSRF-Token': '...' }
}
});
uppyuppy.use(XHRUpload, {
endpoint: '/upload',
headers: { 'X-CSRF-Token': '...' },
fieldName: 'myFile'
});
react-dropzonereact-dropzone はアップロード処理を一切提供しないため、fetch や axios を使って自分で実装する。
const onDrop = useCallback((acceptedFiles) => {
const formData = new FormData();
formData.append('file', acceptedFiles[0]);
fetch('/upload', { method: 'POST', body: formData });
}, []);
| ライブラリ | 推奨用途 | UI 提供 | 拡張性 | フレームワーク対応 |
|---|---|---|---|---|
blueimp-file-upload | ❌ 非推奨(レガシー jQuery システムのみ) | あり | 低い | jQuery 依存 |
fine-uploader | ❌ 非推奨(使用禁止) | あり | 中 | なし(Vanilla) |
dropzone | 軽量でシンプルなアップローダーが必要な場合 | あり | 低い(コールバック中心) | Vanilla / jQuery 不要 |
filepond | 美しい UI と画像処理機能をすぐに使いたい場合 | あり(高品質) | 中(公式プラグイン) | React/Vue 公式ラッパーあり |
react-dropzone | React で UI を完全にカスタマイズしたい場合 | なし(ロジックのみ) | 高(自由に実装) | React 専用 |
uppy | モダンで拡張可能なアップロード体験を構築したい場合 | プラグインで選択可 | 非常に高い(モジュール式) | React/Vue/Vanilla 対応 |
uppy か filepond を第一候補に。どちらもアクティブにメンテナンスされ、豊富な機能と美しい UX を提供する。react-dropzone。ただし、UI 実装コストは高くなる。dropzone。ただし、高度な機能は自前実装になる。blueimp-file-upload と fine-uploader は絶対に新規で使わないこと。セキュリティリスクや将来のメンテナンス負荷が高すぎる。dropzone は軽量でシンプルなドラッグ&ドロップアップローダーを必要とする場合に適している。jQuery に依存せず、CSS で高度にカスタマイズ可能だが、サムネイル生成やプログレス表示など基本機能以外の高度な機能(例:画像編集、クラウド統合)は自分で実装する必要がある。
blueimp-file-upload は jQuery に依存する古くからあるライブラリであり、現在は積極的なメンテナンスが行われていない。新しいプロジェクトでは使用せず、代わりに現代的な代替手段を検討すべきである。既存の jQuery ベースのレガシーシステムに統合する必要がある場合にのみ考慮すること。
filepond は美しい UI と直感的なユーザー体験を重視するプロジェクトに最適である。画像のプレビュー、トリミング、圧縮、EXIF 回転補正など、メディアファイル処理に特化した機能を多数内蔵している。ただし、商用利用には有料ライセンスが必要な機能もある点に注意が必要だ。
fine-uploader は公式 npm パッケージが非推奨(deprecated)となっており、GitHub リポジトリも更新が停止している。新規プロジェクトでの使用は避けるべきであり、代わりに uppy や filepond のようなアクティブにメンテナンスされているライブラリを選ぶことを強く推奨する。
react-dropzone は React 専用で、UI を完全に自分で制御したい開発者向けである。このライブラリはドラッグ&ドロップ領域のロジック(onDrop、onDragOver など)を提供するだけで、見た目やプログレス表示、サムネイル生成は一切含まない。そのため、デザインシステムに厳密に従う必要がある大規模アプリや、既存コンポーネントと統合したい場合に最適だ。
uppy はモダンで拡張可能なファイルアップロードソリューションを求める場合に最適である。クラウドストレージ(Google Drive、Dropbox など)との統合、プログレスバー、サムネイル、ファイルタイプバリデーション、再開可能なアップロードなど、豊富な機能をプラグイン形式で提供する。React、Vue、Vanilla JS など複数の環境で動作し、コミュニティとコアチームによる継続的なメンテナンスも保証されている。
Dropzone is a JavaScript library that turns any HTML element into a dropzone. This means that a user can drag and drop a file onto it, and Dropzone will display file previews and upload progress, and handle the upload for you via XHR.
It's fully configurable, can be styled according to your needs and is trusted by thousands.
Install:
$ npm install --save dropzone
# or with yarn:
$ yarn add dropzone
Use as ES6 module (recommended):
import { Dropzone } from "dropzone";
const dropzone = new Dropzone("div#myId", { url: "/file/post" });
or use as CommonJS module:
const { Dropzone } = require("dropzone");
const dropzone = new Dropzone("div#myId", { url: "/file/post" });
👉 Checkout our example implementations for different bundlers
Use the standalone files like this:
<script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>
<link
rel="stylesheet"
href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css"
type="text/css"
/>
<div class="my-dropzone"></div>
<script>
// Dropzone has been added as a global variable.
const dropzone = new Dropzone("div.my-dropzone", { url: "/file/post" });
</script>
src/options.js
for all available options⚠️ NOTE: We are currently moving away from IE support to make the library more lightweight. If you don't care about IE but about size, you can already opt into
6.0.0-beta.1. Please make sure to pin the specific version since parts of the API might change slightly. You can always read about the changes in theCHANGELOGfile.
If you need support please use the discussions section or
stackoverflow with the dropzone.js tag and not the GitHub issues
tracker. Only post an issue here if you think you discovered a bug.
If you have a feature request or want to discuss something, please use the discussions as well.
⚠️ Please read the contributing guidelines before you start working on Dropzone!
thumbnail(file, data)
and display the image wherever you likeSee LICENSE file