質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

9432閲覧

IE11でjavascriptのformDataを利用してファイルを送信できなくて困っています

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/04/26 00:42

編集2020/04/26 01:34

前提・実現したいこと

javascriptのnew formData()を利用して、コントローラーへファイルデータを渡す方法について、うまくいかなくて困っています。

「画像ファイルのドラッグアンドドロップまたはダブルクリックしてファイル選択」
を行うjavascriptを作成しています。
javascript ES5 クラス形式で作成しているため、jqueryは使用しない前提です。

Google Chromeでは問題なく動作したのですが、Internet Explorer 11に対応できるように変更しようとしています。

サーバー側はASP.NET MVC5(C#)を使用しています。

ご教授お願いします。

発生している問題

・画像ファイルのドラッグアンドドロップについて
Internet Explorer 11では、drop時にevent.dataTransfer.filesから、input fileのfilelistに追加ができないので、代替方法として、formData.appendで、filesをappendしたいのですが、うまくいかなくて困っています。
filelistは取得できていますが、xmlHttpRequest送信時にコントローラーは実行されるが、filesはnullになっています。

input fileのnameはControllerの引数名に合わせないと実行できないため、filesとしています。

new FormData(this._form)をしている理由は、追加のパラメータをHTMLファイルにinputタグで直接記載して利用したいためです。

javascript

1 2var formData = new FormData(this._form); 3formData.append("files", files); 4 5var xhr = new XMLHttpRequest(); 6xhr.open("POST", uploadUrl, true); 7xhr.send(formData); 8

該当のソースコード

・index.cshtml

html

1<div class="row"> 2 <div class="col col-md-6"> 3 @using (Html.BeginForm("Upload", "Test", FormMethod.Post, new { @class = "imagedrop", @id = "imagedrop", name = "imagedrop", enctype = "multipart/form-data" })) { 4 @Html.AntiForgeryToken() 5 @Html.Editor("addId", new { htmlAttributes = new { @id = "addId", name = "addId", style = "display: none" } }) 6 <!-- その他のコードはjavascriptで動的に生成 --> 7 } 8 </div> 9</div> 10 11@section Scripts { 12 <script> 13 var imagedrop = new Imagedrop(); 14 </script> 15}

・TestController.cs

C#

1[HttpPost] 2[ValidateAntiForgeryToken] 3public ActionResult Upload(HttpPostedFileBase[] files, long addId) { 4 var test1 = files; // filesのみnullになる 5 var test2 = addId; // addIdは問題なし 6}

・index.js

javascript

1// 画像ファイルをドラッグ&ドロップ、またはダブルクリックして選択 を行うコード 2// jqueryを使用しないコードで記述してます。 3// 説明用の必要最低限のため、細かな動作のコード、ファイルチェック等は省略しています。 4var Imagedrop = (function () { 5 var Imagedrop = function () { 6 this.init(); 7 } 8 9 Imagedrop.prototype.init = function () { 10 var form = document.getElementById("Imagedrop"); 11 var dragAndDropArea = document.getElementById("dragAndDropArea"); 12 13 var template = "\n" + 14 "<div class=\"drag-and-drop-area\" id=\"dragAndDropArea\">\n" + 15 " <input type=\"file\" id=\"files\" name=\"files\" accept=\"image/jpeg\" style=\"display: none\" />\n" + 16 " <div class=\"default-message\" id=\"defaultMessage\">\n" + 17 " <p>ここに画像ファイルをドラッグ&ドロップ、またはダブルクリックして選択</p>\n" + 18 " <p>(.jpgファイル、1MBまで)</p>\n" + 19 " </div>\n" + 20 " <div class=\"preview-image\" id=\"previewImage\" style=\"display: none\"></div>\n" + 21 " <div class=\"preview-filename\" id=\"previewFileName\" style=\"display: none\"></div>\n" + 22 "</div>\n"; 23 24 dragAndDropArea ? dragAndDropArea.parentNode.removeChild(dragAndDropArea) : null; 25 form.insertAdjacentHTML("afterbegin", template); 26 27 var _self = this; 28 29 this._form = document.getElementById("Imagedrop"); 30 this._dragAndDropArea = document.getElementById("dragAndDropArea"); 31 this._inputFile = document.getElementById("files"); 32 this._defaultMessage = document.getElementById("defaultMessage"); 33 this._previewImage = document.getElementById("previewImage"); 34 this._previewFileName = document.getElementById("previewFileName"); 35 this._files = null; 36 37 this._dragAndDropArea.addEventListener("dragenter", function (event) { 38 event.stopPropagation(); 39 event.preventDefault(); 40 }); 41 42 this._dragAndDropArea.addEventListener("dragover", function (event) { 43 event.stopPropagation(); 44 event.preventDefault(); 45 }); 46 47 this._dragAndDropArea.addEventListener("drop", function (event) { 48 event.stopPropagation(); 49 event.preventDefault(); 50 51 // Google Chromeの方法。Internet Explorer 11はinput fileには追加できない 52 // _self._inputFile.files = event.dataTransfer.files; 53 54 // 代替案 55 _self._files = event.dataTransfer.files; 56 _self.upload(true); 57 }); 58 59 this._dragAndDropArea.addEventListener("dblclick", function (event) { 60 _self._inputFile.click(); 61 }); 62 63 this._inputFile.addEventListener("change", function (event) { 64 _self._files = _self._inputFile.files; 65 _self.upload(false); 66 }); 67 } 68 69 Imagedrop.prototype.upload = function (dragAndDropMode) { 70 var _self = this; 71 var uploadUrl = this._form.action; 72 73 // ドラッグアンドドロップの時のみファイル追加処理 74 if (drapAndDropMode) { 75 var files = this._files; 76 this._inputFile.parentNode.removeChild(this._inputFile); 77 78 var formData = new FormData(this._form); 79 formData.append("files", files); // filesにfilelistはある 80 } else { 81 var formData = new FormData(this._form); 82 } 83 84 var xhr = new XMLHttpRequest(); 85 xhr.open("POST", uploadUrl, true); 86 87     // sendはできているが、画像のドラッグアンドドロップではファイルデータを渡せていない 88 xhr.send(formData); 89 xhr.onreadystatechange = function () { 90 if (xhr.readyState === XMLHttpRequest.DONE) { 91 if (xhr.status == 200) { 92 // ファイルの表示処理 93 } 94 95 xhr.abort(); 96 } 97 } 98 } 99 100 return Imagedrop; 101})();

試したこと

上記のjavascriptコード上でのコメント箇所あたりで試行錯誤しています。

### 補足情報(FW/ツールのバージョンなど) .NET Framework 4.7.1 Visual Studio Express 2012 for Web ASP.NET MVC5(C#)

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/04/26 01:12

いろいろ書かれていますが、問題は、 > Internet Explorer 11では、drop時にevent.dataTransfer.filesから、input fileのfilelistに追加ができない という IE11 に限ったことで、そこだけ解決できれば var formData = new FormData(this._form); の formData には目的のオブジェクトを取得できるので、すべてうまくいくということですか? (要するに ASP.NET MVC 側は関係ない問題ということではないのですか)
退会済みユーザー

退会済みユーザー

2020/04/26 01:22 編集

ご回答ありがとうございます。 IE11に限ったことを解決したいです。 ドロップ時に javasript上で、var formData = new FormData(this._form)に目的のフォームデータが入れば、 ASP.NET MVCのコントローラーのHttpPostedFileBase[] filesにファイルを渡せるので、 ASP.NET MVCのほうはあまり関係がないといえば、そうかもしれません。
退会済みユーザー

退会済みユーザー

2020/04/26 01:37 編集

であれば、タイトルから「IE11 で javascript の formData を利用してファイルを送信できなくて困っています」というように書き換えて、質問文の内容も ASP.NET 色を弱めた方がレスが付きやすいと思います。ASP.NET という言葉を見ただけで中身を見ないでスルーする人が多いと思いますので。逆に JavaScript の話ということになれば、ここ Teratail には詳しい方は多々おられるようですので、レスは付きやすいと思います。 ところで、IE11 はいろいろサポートしてないことが多いのですが、そもそも IE11 のサポート外で無理なことをしているというようなことはないでしょうか? Chrome は問題ないが IE11 はダメということですので、IE11 のサポート外が疑わしいのですが。 そのあたりは事前に調べましたか?
退会済みユーザー

退会済みユーザー

2020/04/26 01:37

了解しました。javascriptの質問をしたく、teratrailは初めてでしたので気づきませんでした。 タイトルを変更してます。 IE11は formDataでappendぐらいしか使用できないことと、input fileに直接filelistを追加できないことまでを把握しています。そのほかの部分はわかっていません。
guest

回答1

0

ベストアンサー

ASP.NET MVC5はわかりませんが、ブラウザに表示されたHTMLとJavaScriptの問題と思いますので回答いたします。

MDN FormData#append をみると、第二引数の value は string or Blob(派生のFileも可) ですので、得られた filesFileList)を追加するのではなく、個別に追加してみてはいかがでしょう。

javascript

1 var files = (event.dataTransfer||event.target).files; 2 for( var i=0; i<files.length; ++i ) { 3 var file = files[i]; 4 formData.append("files", file, file.name); 5 }

また、DnD操作時の予期せぬ動作に備え、dragover等のタイミングで ev.dataTransfer.dropEffect="copy" の指定も検討されてはいかがでしょうか。
HTML ドラッグ&ドロップ API


追記)

回答では、第一引数にフィールド名 "files" を繰り返す実装ですが、
複数個あるinput[type=checkbox][name=hoge] のデータを application/x-www-form-urlencoded でPOSTするとhoge=val&hoge=val2 のようなデータが送信されるのと同様に multipart/form-data でもフィールド名の重複が認められます(サーバー側が解釈するなら正しく動作するはずです)。

投稿2020/04/26 01:15

編集2020/04/26 01:34
AkitoshiManabe

総合スコア5432

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

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

退会済みユーザー

退会済みユーザー

2020/04/26 01:35

コメントありがとうございます。 上記の fileを個別に追加する方法で対応できるか、試してみます。
退会済みユーザー

退会済みユーザー

2020/04/26 02:48 編集

filelistをfileごとに個別に追加する方法で実行することができました。 ありがとうございます。 dropoverイベント時のe.dataTransfer.dropEffect="copy" についても追加したいと思います。とても参考になりました。
AkitoshiManabe

2020/04/26 04:15

解決されてよかったです。 > Google Chromeでは問題なく動作したのですが これは知りませんでしたので、「FormData#append() の実装も進化しそう」との勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問