dropzone.js + Laravel8で画像アップロード機能を実装する
何ができる?
こんな感じで複数画像アップロード+プレビューを簡単に実装できる
ちなみにデフォルトでは、画像はドロップした瞬間にサーバー側にアップロードされます
(autoProcessQueueをfalseに設定することで無効にすることは可能)
フロント(表示)側の実装方法
準備
公式サイトによるとnpm,yarnもしくはスタンドアローン方式にどちらかが選べる
今回は簡単なスタンドアローン方式で
<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" />
html(blade)ファイルのhead内に記載する
表示
htmlで書く場合
<form action="/file-upload" class="dropzone" id="my-awesome-dropzone"></form>
ファサードを使う場合
{{Form::open(['url' =>'/file', 'files' => true, 'class' => 'dropzone', 'id' => 'my-awesome-dropzone'])}}
{{Form::close()}}
以上。
これだけでOK
注意点
このformは画像アップロード専用なので要注意
他にも送信したい項目がある場合は別フォームを用意する
<!-- 画像アプロード用 -->
{{Form::open(['url' =>'/file', 'files' => true, 'class' => 'dropzone', 'id' => 'my-awesome-dropzone'])}}
{{Form::close()}}
<!-- 入力項目送信用 -->
{{Form::open(['url' =>'/input', 'files' => false])}}
{{ Form::select('hoge', hoge, null) }}
{{Form::close()}}
オプション
かなり色々なオプションが指定できる
また、各種メッセージがデフォルトでは英語になってるので日本語にする必要もありそう。
<script>
const dropzone = new Dropzone( '#my-awesome-dropzone', {
maxFilesize: 5, // 最大ファイズサイズ(MB)
maxFiles: 7, // 最大ファイルアップロード数
timeout: 2000, // タイムアウト(ms)
addRemoveLinks: true, // 削除用リンクを追加するか
acceptedFiles: '.jpeg,.jpg,.png,.gif', // 許容するファイルタイプ
dictDefaultMessage: 'ファイルをドラッグ&ドロップしてね。', // アップロードエリアの表示メッセージ
dictInvalidFileType: 'このファイルタイプはサポートされてないよ。', // サポート外の時に表示するメッセージ
dictMaxFilesExceeded: 'これ以上アップロードできないよ。', // 最大アップロード数を超えたときのメッセージ
}).on("success", function(file, serverResponse){
// アップロードが成功した時にここにくる
}).on("removedfile", function(file){
// ファイルを削除した時にここにくる
// サーバーからファイルを削除するajaxなどを実装する
});
</script>
サーバーサイドの実装
<!-- 画像アプロード用 -->
<form action="{{route('dropzone.store')}}" method="post" name="file" files="true" enctype="multipart/form-data" class="dropzone">
先ほどのHTMLのaction部分を修正
(dropzoneからアップロードされた画像を取得するためのURLを設定)
use App\Http\Controllers\DropZoneController;
Route::post('dropzone/store', [DropZoneController::class, 'dropzoneStore'])->name('dropzone.store');
ルーティングファイルに、上記のactionで指定したrouteを設定
class DropZoneController extends Controller
{
public function dropzoneStore(Request $request)
{
$image = $request->file('file');
$imageName = time() . '.' . $image->extension();
$image->move(public_path('uploads'), $imageName);
return response()->json(['success' => $imageName]);
}
}
フロント側から送信されたファイルを受け取ってドキュメントルートのuploadsディレクトリに保存する例
編集画面で初期イメージを設定する
編集フォームで既に登録済みの画像をデフォルト表示する方法
<script>
const dropzone = new Dropzone( '#my-dropzone', {
maxFilesize: 5,
maxFiles: 10,
init : function() {
let mockFile = { name: "filename", size: 123 };
this.displayExistingFile(mockFile, "https://hoge.com/storage/uploads/h.jpg");
// maxFilesオプションを指定してる場合はこれを指定する
this.options.maxFiles = this.options.maxFiles - 1;
}
参考:https://github.com/enyo/dropzone/wiki/FAQ#how-to-show-files-already-stored-on-server
ここまで作って気がついたんですが、編集フォームでアップロード画像を更新する場合は
autoProcessQueue: false
を使ってサブミット時に画像を送信するように変更しないとダメそう
なぜなら、編集画面でサブミットボタンを押す前に画像を更新して離脱されると、ユーザは更新してるつもりがなくてもサーバから画像は削除されてり変更されてしまうから。
あとがき
このようにDropzoneを使うと非常に簡単にファイルのアップロードが実装できます
ただし、ユーザがファイルを削除した時に、サーバー側でアップロード済みの画像を削除したりするのは開発者側で実装しないといけません
こんな感じで、細かく見るとあまり痒いところに手は届いてない感がありますが、「それが面倒なら有料版のPlusを使ってください」という意味なのだと思います
ディスカッション
コメント一覧
まだ、コメントがありません
みんながLoadingしてる記事
新たにPostされた記事
: JS
Dropzone.jsで編集画面を作る(アップロード済みの画像を表示)
前回からの続きです Dropzone.jsを使って画像アップロードの編集画面を作 ...: Laravel
LaravelでDBテーブルをupdateした時に、同時に更新した値を取得する裏技[Laravel8]
通常Eloquentのsaveやupdateでは、実行時に更新した値の結果を返し ...: JS
忘れがちなJqueryのあれやこれ
Jqueryって何でこんなに忘れやすいのでしょうか 呪文にかかったくらい覚えられ ...: 資格
理系エンジニアの僕がTOEICで800点をとるためにした勉強
先日、TOEIC L&R テストで800点を超えました 今回は理系エンジ ...: Laravel
[Laravel8]npm run devが失敗する場合の解決法
Laravel8にJetstreamをインストールする際、npm run dev ...HashMap
Created by
はやぴ
Web/アプリ開発エンジニア
Sierにてお堅いB向けのソフトウェア開発を経て、現在はC向けのWebやアプリを中心に開発しています。
そのほか