input要素に画像を選択したら、裏側でストレージ保存してくれる機能を実装したく
Ajaxを使用しました。
フォーム形式でないデータをAjaxで扱ったことはあるものの、フォームデータは初めてでかなり詰まってしまいました。
今後のためにメモメモ。
HTML側
HTMLは普通のフォームタグとtype=fileのinputタグです。
今回は必要ないのでformタグにid属性をつけていません。
<form method="POST" accept=".png,.jpg,.jpeg,.gif"> <h3>画像アップロード</h3> <input type="file" class="js-droparea" id="upload_file" name="upload_file"> </form>
JS側
ちょっと長いですが、大事なのは前半の送信データ作成部分です。
$dropArea.on('change', function () { //画像情報が入って(changeしたら)きたら var fd = new FormData(); //画像データ送信に必要なFromDataインスタンス作成 fd.append('image', $(this).prop('files')[0]); //取得した画像データを追加 $.ajax({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'), }, url: 'create/store_image', type: 'POST', data: fd, processData: false, // jQuery がデータを処理しないよう指定 contentType: false, // これがないと渡ったデータがおかしくなりphpで処理できない dataType: 'text' }) .done(function (result) { if (result == 'success') { alert('ok'); } else if (result == 'error') { alert('error'); } else { alert('その他です'); } }) .fail(function (data) { alert('通信に失敗しました'); }) });
.done以降はPHPから返ってきた値によって分岐しています。
通信が成功したら’success’, 失敗したら’error’がPHP側からかえるようにしています。
(なので dataType: ‘text’ としています)
詰まりポイント
data: の指定
JSからPHP側にリクエストは届くのに、どうしてもフォームデータが入ってきません。
結果的には、初め
data: { 'file': fd, },
としていたのを、
data: fd,
と書くことで解決しました!!
contentType:false
上で散々書き換えている間にコメントアウトしてしまっていた
contentType: false
こちらもフォームデータ送信に重要なものでした。
やっと送信できたフォームデータの中身が文字化けして何も取得できなかったのですが、
こちらのコメントアウトを外したらちゃんとデータを
$request->file('image')
で取れるようになりました。
ddできない
Ajaxの時はdd()しても表示されない。。と思っていましたが、
ddした内容は開発ツールの Response や Previewタグで表示できるようです。
開発ツールを開いて NetWorkタブをクリック→Fetch/XHRタブをクリック
Payload タブではこちらからの送信データが表示されます。
(contentType: false, をコメントアウト時のみ)
Laravelコントローラーでの取得
無事にデータがコントローラーへ渡せたら、
public function storeImage(Request $request) { $img = $request->file('image'); ....後続の処理
のようにいつも通りの処理でデータを受け取れます!