ASP.NET MVC - ファイルアップロード(fetch 版)
ASP.NET MVC - ファイルアップロード(fetch 版)
ASP.NET MVC でファイルをアップロードする方法を解説します。
ここでは JavaScript から fetch() を使ってアップロードする方法のみ解説します。
ファイルアップロードの基礎は「ASP.NET MVC でファイルアップロード」を参照してください。
以下の環境で確認しています。
- .NET Framework 4.6.2
- AspNet.Mvc 5.2.9
サンプルソース
HTML + JavaScript
<input type="file">
で選択されたファイルを JavaScript から送信します。
fetch() を使って FormData を送るイメージです。
<input type="file" name="uploadFile" />
<input type="button" value="アップロード" />
<script>
document.addEventListener('DOMContentLoaded', function () {
// アップロードボタンにクリックイベント追加
const uploadButton = document.querySelector('input[type="button"]');
uploadButton.addEventListener('click', function () {
const formData = new FormData();
const fileElem = document.querySelector('input[type="file"]');
formData.append('uploadFile', fileElem.files[0]);
upload(formData);
});
});
async function upload(formData) {
try {
const response = await fetch('/File/Upload', {
method: 'POST',
body: formData,
});
if (!response.ok) {
switch (response.status) {
case 400:
alert('ファイルを選択してください');
break;
default:
alert('アップロードに失敗しました');
break;
}
return;
}
alert('アップロード成功');
} catch (error) {
alert('予期せぬエラー');
}
}
</script>
アクションメソッド
大枠は form で送る版と大して変わりありません。
View() で HTML を返すのではなく、HttpStatusCodeResult クラスを使ってステータスコードを返すようにしています。
アップロード成功 → 200 OK
アップロードファイル未選択 → 400 Bad Request
例外発生 → 500 Internal Server Error
応答の方法はいろいろあるので、ケースバイケースで試してみればよいかと。
(たとえば Json に処理結果、メッセージを入れて返すなど)
[HttpPost]
public ActionResult Upload(HttpPostedFileBase uploadFile)
{
// 何も選択せずアップロードされた場合は入力エラー
if (uploadFile == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
try
{
// アップロードされたファイルの保存先を ~/App_Data/Uploaded/[Guid]/元のファイル名 にする
var path = Path.Combine(Server.MapPath("~/App_Data/Uploaded"),
Guid.NewGuid().ToString(),
Path.GetFileName(uploadFile.FileName));
// ディレクトリがなければ作る
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
}
// アップロードされたファイルを保存する
uploadFile.SaveAs(path);
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
catch (Exception)
{
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
}
}
複数ファイルのアップロード
HTML
<input type="file">
に multiple 属性を付けます。
<input type="file" name="uploadFiles" multiple />
<input type="button" value="アップロード" />
FormData に append する部分を、選択されたファイルの数だけ繰り返すようにします。
formData.append('uploadFile', fileElem.files[0]);
↓
for (let i = 0; i < fileElem.files.length; i++) {
formData.append('uploadFiles', fileElem.files[i]);
}
(補足)ファイルの数だけ FormData に append してください。
次のように fileElem.files をそのまま指定した場合、アクションメソッドの引数の Count は 0 になります。
// ★これは良くない例★
// アクションメソッドにデータが渡されない
// (uploadFiles.Count() が 0 になる)
formData.append('uploadFiles', fileElem.files);
アクションメソッド
form タグで送る版と大差ないです。
仮引数の型をリストにして、リストの件数分、処理を繰り返すだけです。
以下のコードは、アップロードされたファイルすべてを Web アプリルートの App_Data/Uploaded/[Guid] フォルダに元のファイル名で保存します。
[HttpPost]
public ActionResult Upload(IEnumerable<HttpPostedFileBase> uploadFiles)
{
// 何も選択せずアップロードされた場合は入力エラー
if (uploadFiles == null || !uploadFiles.Any())
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
// アップロードされたファイルの保存先を ~/App_Data/Uploaded/[Guid] フォルダにする
var folderPath = Path.Combine(Server.MapPath("~/App_Data/Uploaded"),
Guid.NewGuid().ToString());
// フォルダがなければ作る
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
// アップロードされたファイルすべてを、所定のフォルダに元のファイル名で保存する
foreach (var file in uploadFiles)
{
file.SaveAs(Path.Combine(folderPath, Path.GetFileName(file.FileName)));
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
アカウントを作成 して、もっと沢山の記事を読みませんか?
この記事にコメントをしてみませんか?