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

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

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

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JavaScript

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

ASP.NET MVC Framework

ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

Q&A

2回答

5353閲覧

<input type="file" multiple />で前回選択したファイルを保持しつつ複数回ファイル選択ができるようにしたい

j_t

総合スコア13

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JavaScript

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

ASP.NET MVC Framework

ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

0グッド

0クリップ

投稿2019/09/03 01:30

編集2019/09/03 08:29

<input type="file" multiple/>でファイルを選択後、再度ファイルを選択すると前回選択したファイルの情報が消えてしまいます。
複数のフォルダからファイルを選択できるように選択済みファイルが追加されていく形にしたいのですが上手く行きません。

教えていただけると大変助かります。

開発環境はVisual Studio2019
フレームワークはASP.NET MVC5
プラグインでjQuery v3.3.1が入っています。

以下のようにコードを書いたのですが、Controllerでfilesを受け取っても、直前に選択されたファイルの情報しか受け取れませんでした。

View

1@using (Html.BeginForm( null, "Upload", FormMethod.Post, new { enctype = "multipart/form-data" })) 2{ 3 <input id="files" name="files" type="file" style="display: none;" onchange="checkFile();" multiple /> 4 <button type="button" class="btn btn-primary" onclick="$('#files').click();"> 5 <i class="glyphicon glyphicon-file"></i> ファイル選択 6 </button> 7 8  <button id="btnUpload" type="submit" class="btn btn-primary"> 9    <i class="glyphicon glyphicon-cloud-upload"></i> ファイルアップロード 10  </button> 11} 12 13@section scripts { 14 <script> 15 var selectedFiles = new Array(0); // これまでに選択された全ファイルを含む配列 16 17 function checkFile() { 18 var files = document.getElementById("files").files; // 選択されたファイル 19 20 for (i = 0; i < files.length ; i++) { 21 selectedFiles.push(files[i]); 22 } 23 24 document.getElementById("files").files = selectedFiles; 25 } 26 </script> 27}

C#

1//受け取り側のコントロール 2[HttpPost] 3public ActionResult FileUpload(HttpPostedFileBase[] files) 4{ 5~~~ 6}

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

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

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

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

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

m.ts10806

2019/09/03 01:40

ブラウザの仕様的に無理だろうな・・・とは思いますが(ローカルファイルを直接いじれないので) なぜそうしたいのでしょうか。
j_t

2019/09/03 01:44

理由を追記しました。 複数のフォルダからファイルを選択できるようにしたいためです。
m.ts10806

2019/09/03 01:47

複数type=fileを設置してはと。
j_t

2019/09/03 01:58

複数type=fileを設置した場合、Controller側でまとめて取得できるでしょうか?
m.ts10806

2019/09/03 02:00

「まとめて取得」がどうしたいのか分かりませんが、 作った分だけname指定して取ればいいですし、面倒なら name=files[] のように配列にすると良いかと思います。
j_t

2019/09/03 02:25

アドバイスありがとうございます。参考にさせていただきます。
退会済みユーザー

退会済みユーザー

2019/09/03 02:45

ASP.NET MVC アプリの話のようですが、そうであれば ASP.NET のタグを付けてください。あと、開発環境(Visual Studio, .NET, MVC のバージョンなど)を書いてください(コメントに書くのでなく質問欄を編集して)。CORE ではないですよね?
j_t

2019/09/03 05:28

質問欄を編集して不足情報を付け加えました。
退会済みユーザー

退会済みユーザー

2019/09/03 07:01

タグの方もお願いします。ASP.NET, ASP.NET MVC Framework というタグがあります。
退会済みユーザー

退会済みユーザー

2019/09/03 10:17 編集

自分の環境で MVC5 アプリで検証してみましたが、フォルダが異なる複数のファイルを一度にアップするのは普通のやり方ではどうしてもダメで、nt4c さんがレスに書かれたようにブラウザの HTML5 File API と FormData を利用するのがよさそうです。 後で、検証に使ったコードその他を整理して回答欄に書いておきます。
guest

回答2

0

input[type=file]要素の持つfilesは配列ではなくFileListですのでdocument.getElementById("files").files = selectedFiles;としてもファイルをセットすることはできません。

ですので、配列にfileを格納するのではなくFileListごと格納しFormDataを使って送信する方法はどうでしょうか。

js

1const selectedFiles = [] 2$('#input').on('change', function(event) { 3 selectedFiles.push(event.target.files) 4}) 5 6function submit() { 7 const formData = new FormData(); 8 selectedFiles.forEach(function(element) { 9 formData.append("data[]", element); 10 }); 11 $.ajax({ 12 url: '/api', 13 method: 'post', 14 dataType: 'json', 15 data: formData, 16 processData: false, 17 contentType: false 18 }).done(function() { 19 }).fail(function() { 20 }); 21} 22

もし選択されているファイルをユーザー側で削除させたいなどの機能を作る場合はwindow.URL.createObjectURL()の利用を検討されてみてもよいかもしれません。
ページを開いている間のみ有効な一時的なBlobURLを生成しますので、選択ファイルを個別に操作させたい場合は有効です。

js

1var selectedFiles = [] 2$('#input').on('change', function(event) { 3 for(const item of event.target.files) { 4 selectedFiles.push(URL.createObjectURL(item)) 5 } 6})

投稿2019/09/03 03:43

nt4c

総合スコア768

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

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

j_t

2019/09/03 23:40

丁寧なご回答ありがとうございます。 参考にさせていただきます。
guest

0

自分の環境(Visual Studio Community 2015, .NET 4.6.1, MVC5)で検証してみました。

フォルダが異なる複数のファイルを一度にアップするのは普通のやり方(form を submit する方法。下のサンプルコードで言うと[Upload by Submit]ボタンをクリック)ではどうしてもダメでした。

nt4c さんがレスに書かれたようにブラウザの HTML5 File API と FormData を利用し Ajax で送信するのがよさそうです。

以下に検証に使ったコードを書いておきます。説明はコメントにありますのでそれを見てください。手抜きでスミマセン。不明点があれば質問してください。

Model

public class MultipleUploadModels { public string CustomField { get; set; } public IList<HttpPostedFileBase> PostedFiles { get; set; } }

View

@model Mvc5App.Controllers.MultipleUploadModels @{ ViewBag.Title = "MultipleUpload"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>MultipleUpload</h2> @using (Html.BeginForm("MultipleUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.AntiForgeryToken() // name 属性はモデルのクラスのプロパティ名と同じにしない // とサーバー側でモデルバインディングされないので注意。 // 大文字小文字は区別しない。 <input id="mutiplefileupload" type="file" name="postedfiles" multiple="multiple" /> <button type="submit">Upload by Submit</button> <br /> @Html.Raw(ViewBag.Result) } <br /> <input type="button" id="ajaxUpload" value="Ajax Upload" /> <br /> <div id="result"></div> @section Scripts { <script type="text/javascript"> //<![CDATA[ // FormData オブジェクトの利用 // https://developer.mozilla.org/ja/docs/Web/Guide/Using_FormData_Objects // ブラウザの HTML5 File API サポートを確認 if (window.File && window.FileReader && window.FileList) { // FormData オブジェクトの利用 // CSRF 用のトークンを取得するため form から FromData を取得 var fd = new FormData(document.querySelector("form")); // input type=file" でファイルの選択が完了すると change // イベントが発生するのでそれにリスナをアタッチし、そこ // で FileList オブジェクトを取得して選択した各ファイル //(File オブジェクト)を FormData に追加 var fileUpload = document.getElementById("mutiplefileupload"); fileUpload.addEventListener('change', function (e) { // files プロパティで FileList オブジェクトを取得 var filelist = fileUpload.files; for (let i = 0; i < filelist.length; i++) { // File オブジェクトを FormData に追加 // 名前 "postedfiles" はモデルのプロパティ名と同じにする fd.append("postedfiles", filelist[i]); } }); // [Ajax Upload] ボタンクリックの処置 $('#ajaxUpload').on('click', function (e) { $.ajax({ url: '/home/multipleupload', method: 'post', data: fd, processData: false, // jQuery にデータを処理させない contentType: false // contentType を設定させない }).done(function (response) { $("#result").empty; $("#result").html(response); }).fail(function (jqXHR, textStatus, errorThrown) { $("#result").empty; $("#result").text('textStatus: ' + textStatus + ', errorThrown: ' + errorThrown); }); }); } else { $("#result").empty; $("#result").text('File API がサポートされてません。'); } //]]> </script> }

Controller / Action Method

public ActionResult MultipleUpload() { return View(); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult MultipleUpload(MultipleUploadModels model) { string result = ""; IList<HttpPostedFileBase> postedFiles = model.PostedFiles; if (postedFiles != null && postedFiles.Count > 0) { foreach (HttpPostedFileBase postedFile in postedFiles) { if (postedFile != null && postedFile.ContentLength > 0) { // アップロードされたファイル名を取得。ブラウザが IE の // 場合 postedFile.FileName はクライアント側でのフル // パスになることがあるので Path.GetFileName を使う string filename = Path.GetFileName(postedFile.FileName); // 保存ホルダの物理パス\ファイル名 string path = Server.MapPath("~/UploadedFiles") + "\" + filename; // アップロードされたファイルを保存 postedFile.SaveAs(path); result += filename + " (" + postedFile.ContentType + ") - " + postedFile.ContentLength.ToString() + " bytes アップロード完了<br />"; } } } else { result = "ファイルアップロードに失敗しました"; } if (Request.IsAjaxRequest()) { return Content(result); } else { ViewBag.Result = result; return View(); } }

実行結果は以下の画像のようになります。使ったブラウザは Chrome 76.0.3809.132 です。

ファイルの選択

これより先に Migration フォルダの画像を一つ選択しています。

イメージ説明

ファイルアップロード完了後の応答画面

[Ajax Upload]ボタンをクリックして Ajax でファイルを 3 つ送信し、戻ってきた応答を表示したものです。

イメージ説明

アップロードしたファイル

期待通りサーバー側の指定フォルダに保存されています。

イメージ説明

投稿2019/09/03 07:24

編集2019/09/03 09:26
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

j_t

2019/09/04 00:21

お手数をおかけしてすみません。 大変ご丁寧な回答ありがとうございます。 参考にさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問