🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

1回答

1123閲覧

Laravelで、FormDataを使用して$.ajaxで複数回送信した場合に$_FILESの中身が同一とならない

Reoh

総合スコア0

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2021/03/03 00:50

編集2021/03/03 00:52

前提・実現したいこと

現在、Laravelで画像を投稿するフォームを作成しています。
この時、通常のsubmitボタンと、投稿を一時保存するボタンの2つに分け、
submitは通常通りpostさせて、一時保存の場合はajaxを使用し、画面を表示し続けたまま投稿する処理としました。

この場合に、Controller側でバリデーションを作成するため、
__$_FILES__の中身の情報を使ってデータの情報を取得しようとした際、Chrome、Edgeと、IE11で動作差分が出ており、
特にIE11でエラーが発生する挙動となってしまっており、修正したいのですが何が原因なのかまったく見当がつかない状態ですのでご教示いただけないでしょうか。

発生している問題・エラーメッセージ

一時保存ボタンを複数回選択した際、 Chrome、Edgeでは$_FILESの中の配列情報の定型が保持され続けるが、 IE11のみ配列情報が保持されない。

該当のソースコード

formphp

1... 2 3<form action="{{route('confirm')}}" method="POST" name="post" enctype="multipart/form-data" id="post"> 4 <input type="text" name="title" id="title" value="{{old('title')}}" minlength="1"> 5 <input type="file" name="upfile[]" accept='image/*' class="uplaod-files" id="button1"> 6 <input type="file" name="upfile[]" accept='image/*' class="uplaod-files" id="button2"> 7 <input type="file" name="upfile[]" accept='image/*' class="uplaod-files" id="button3"> 8 <input type="file" name="upfile[]" accept='image/*' class="uplaod-files" id="button4"> 9 10 <button id="OneTimeSave">一時保存する</button> 11 <button type="submit">入力内容の確認へ</button> 12</form> 13 14... 15 16<script> 17 //一時保存ボタン押下時処理 18 $("#OneTimeSave").on("click",function(){ 19 $('#OneTimeSave').prop('disabled',true); 20 var formData = new FormData($("#post").get(0)); 21 var url = "{{ route('OneTimeSave')}}"; 22 $.ajax({ 23 url:url, 24 type:"POST", 25 data:formData, 26 contentType:false, 27 processData:false, 28 }).done(function(data){ 29 $('#OneTimeSave').prop('disabled',false); 30 alert("一時保存に成功しました!"); 31 }).fail(function(){ 32 $('#OneTimeSave').prop('disabled',false); 33 alert("一時保存失敗…。"); 34 }); 35 return false; 36 }); 37</script> 38 39...

postController

1public function oneTimePost(Request $request) 2 { 3 $extensions = "(jpg|jpeg|png|bmp)"; 4 foreach ($_FILES['upfile']['type'] as $type) { 5 if(!(empty($type)) && (preg_match($extensions, $type) === 0)) { 6 return response("extension_error", 400); 7 } 8 ...(以降、他バリデーションや保存処理)

問題となっている情報

ChromeEdge

1id="button4"にのみ画像を添付した場合… 2一時保存を複数回選択した場合でも、$_FILESから以下の情報が取得できる。 3 4{"FILES": 5 {"upfile": 6 {"name":["","","","gazou4.jpg"], 7 "type":["","","","image/jpeg"], 8 "tmp_name":["","","","/tmp/phpnJS3hW"], 9 "error":[4,4,4,0], 10 "size":[0,0,0,287928] 11 } 12 } 13}

IE11

1id="button4"にのみ画像を添付した場合… 2一時保存を複数回選択した場合、1回目はChromeやEdgeと同様だが 32回目以降は$_FILESの中身が以下となる。 4 5{"FILES": 6 {"upfile": 7 {"name":["gazou4.jpg"], 8 "type":["image/jpeg"], 9 "tmp_name":["/tmp/phpnJS3hW"], 10 "error":[0], 11 "size":[287928] 12 } 13 } 14} 15 162回目以降であっても、ChromeやEdgeの動作と同様に、 17添付されていないインプットタグの部分はemptyとなるようにしたい

試したこと

現在わかっていることとして、一時保存後ページのリロードを挟めば該当の状況にはならず、
同一セッションで何度も一時保存を行った場合に$_FILESの中身が変わってしまうという状況を確認しています。
尚、IE11の2回目以降の動作の場合で、途中でほかの画像を添付した場合には、添付したファイルの情報が追記される形とはなりますが、
その場合でも画像が添付されていないフォームの情報は空とならずそもそも$_FILESから失われている状況が継続します。

補足情報(FW/ツールのバージョンなど)

・Chromeバージョン : 88.0.4324.190(Official Build)(64 ビット)
・Edgeバージョン  : 88.0.705.81 (公式ビルド) (64 ビット)
・Laravelバージョン : Laravel Framework 6.4.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/03/03 01:10

そもそも、LaravelでPHPのスーパーグローバル変数直に使ってる時点で実装としておかしいような
退会済みユーザー

退会済みユーザー

2021/03/03 02:45

Laravelユーザーはもうこんなコード書いてない。PHPもJSも古い知識を全部捨てて学習し直さないとLaravelは使えない。
yambejp

2021/03/03 03:58

おもいきってIEを切るくらいの勇気がなければ、 解決のための知識は数倍必要になるけど、ほんとにやる気ありますか?
Reoh

2021/03/03 04:34

>>そもそも、LaravelでPHPのスーパーグローバル変数直に使ってる時点で実装としておかしいような ごもっともではあります…。既存ものを対応しているのですが、スーパーグローバル変数を直に使う処理が大量に存在している(!)ので時間的に直そうにも直せず、という状況になります。 >>おもいきってIEを切るくらいの勇気がなければ、 >>解決のための知識は数倍必要になるけど、ほんとにやる気ありますか? 私としてもIE自体は切ってしまいたいところではあるのですが、已むに已まれず対応をしなければならない状態となっています。
guest

回答1

0

自己解決

そもそもそれはどうなの?というお話になりそうなのですが、
以下のように、allFiles()を利用し、nameで各フォームの添付状況を判別したうえで、配列化、
$_FILES['upfile']と同じ形式に落とし込んで代入することにより、一応の解決を行うことができました。

postController

1if(empty($request->allFiles()['button1'])) 2{ 3 $button1= ['name' => "", 'type' => "", 'tmp_name' => "", 'error' => 4, 'size' => 0]; 4} else { 5 $button1=[ 6 'name' => $request->allFiles()['button1']->getClientOriginalName(), 7 'type' => $request->allFiles()['button1']->getClientMimeType(), 8 'tmp_name' => $request->allFiles()['button1']->getPathname(), 9 'error' => $request->allFiles()['button1']->getError(), 10 'size' => $request->allFiles()['button1']->getSize() 11 ]; 12} 13 14if(empty($request->allFiles()['button2'])) 15{ 16 $button2= ['name' => "", 'type' => "", 'tmp_name' => "", 'error' => 4, 'size' => 0]; 17} else { 18 $button2= [ 19 'name' => $request->allFiles()['button2']->getClientOriginalName(), 20 'type' => $request->allFiles()['button2']->getClientMimeType(), 21 'tmp_name' => $request->allFiles()['button2']->getPathname(), 22 'error' => $request->allFiles()['button2']->getError(), 23 'size' => $request->allFiles()['button2']->getSize() 24 ]; 25} 26 27if(empty($request->allFiles()['button3'])) 28{ 29 $button3= ['name' => "", 'type' => "", 'tmp_name' => "", 'error' => 4, 'size' => 0]; 30} else { 31 $button3= [ 32 'name' => $request->allFiles()['button3']->getClientOriginalName(), 33 'type' => $request->allFiles()['button3']->getClientMimeType(), 34 'tmp_name' => $request->allFiles()['button3']->getPathname(), 35 'error' => $request->allFiles()['button3']->getError(), 36 'size' => $request->allFiles()['button3']->getSize() 37 ]; 38} 39 40if(empty($request->allFiles()['button4'])) 41{ 42 $button4= ['name' => "", 'type' => "", 'tmp_name' => "", 'error' => 4, 'size' => 0]; 43} else { 44 $button4= [ 45 'name' => $request->allFiles()['button4']->getClientOriginalName(), 46 'type' => $request->allFiles()['button4']->getClientMimeType(), 47 'tmp_name' => $request->allFiles()['button4']->getPathname(), 48 'error' => $request->allFiles()['button4']->getError(), 49 'size' => $request->allFiles()['button4']->getSize() 50 ]; 51} 52 53$_FILES['upfile'] = [ 54 'name' => [ 55 $button1['name'], 56 $button2['name'], 57 $button3['name'], 58 $button4['name'] 59 ], 60 'type' => [ 61 $button1['type'], 62 $button2['type'], 63 $button3['type'], 64 $button4['type'] 65 ], 66 'tmp_name' => [ 67 $button1['tmp_name'], 68 $button2['tmp_name'], 69 $button3['tmp_name'], 70 $button4['tmp_name'] 71 ], 72 'error' => [ 73 $button1['error'], 74 $button2['error'], 75 $button3['error'], 76 $button4['error']], 77 'size' => [ 78 $button1['size'], 79 $button2['size'], 80 $button3['size'], 81 $button4['size'] 82 ] 83];

ただし、根本的な解決とはなっていないため、折を見てベースの処理から見直していきたいと思います。

投稿2021/03/03 05:51

Reoh

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問