有鑑於公司突然有個case
需要使用Ajax傳送檔案到後端Parser
再吐model到前端
參考了網路許多作法
大部分都是使用jquery的ajax
回傳Json之後再去組前端
但我想了想...
這樣就不能盡情使用MVC內建的Data Binding了阿!
於是我開始想方設法用MVC內建的Ajax將檔案傳送到後端(內建不支援)
有幸在stackoverflow尋獲大神的補帖
特此紀錄一下
後端部分其實跟一般操作表單傳送檔案沒有什麼差異
DemoController.cs
namespace AjaxPostFileDemo.Controllers
{
public class DemoController : Controller
{
// GET: Demo
public ActionResult Index()
{
return View();
}
public ActionResult AjaxPost()
{
return View();
}
[HttpPost]
public ActionResult AjaxPost(HttpPostedFileBase attachment)
{
ViewData.Model = attachment.FileName;
return View();
}
}
}
主要是前端的一段Script
Index.cshtml
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Ajax.BeginForm("AjaxPost", null, new AjaxOptions
{
UpdateTargetId = "ajaxTargetDiv"
}, new { enctype = "multipart/form-data" }))
{
<div class="well">
<div class="row">
@Html.Label("選擇檔案", new { @class = "col-sm-2 control-label" })
<div class="col-sm-10">
<input type="file" name="attachment" class="form-control" />
</div>
</div>
<div class="form-group row">
<div class="col-sm-offset-8 col-sm-4">
<button type="submit" class="btn btn-primary">送出</button>
</div>
</div>
</div>
}
<div id="ajaxTargetDiv">
@Html.Action("AjaxPost")
</div>
@section scripts{
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script>
window.addEventListener("submit", function (e) {
var form = e.target;
if (form.getAttribute("enctype") === "multipart/form-data") {
if (form.dataset.ajax) {
e.preventDefault();
e.stopImmediatePropagation();
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
if (form.dataset.ajaxUpdate) {
var updateTarget = document.querySelector(form.dataset.ajaxUpdate);
if (updateTarget) {
updateTarget.innerHTML = xhr.responseText;
}
}
}
};
xhr.send(new FormData(form));
}
}
}, true);
</script>
}
AjaxPost.cshtml
@model string
<div class="alert-danger ">
你選擇的檔名是 @Model
</div>
實測結果如下圖
這種好用的東西
當然是快點打包成.js檔備著用啊!
-------------後記-------------
20180312
上次改完這段script之後
今天莫名其妙的又踩到雷了
想說來用AjaxOption裡面OnSuccess改個效果
結果發現Onxxxx的全都失效了(畢竟人家本來就不給你傳file阿...)
解法就是在updateTarget.innerHTML = xhr.responseText;下方多一個onComplete();
updateTarget.innerHTML = xhr.responseText;
onComplete();
恩...然後自己override一個onComplete
function onComplete(){
alert("complete test!");
}