2013-09-27 140 views
32

我試圖用這裏提到How to do a ASP.NET MVC Ajax form post with multipart/form-data?Ajax.BeginForm在MVC上傳文件

一個例子,但我不斷收到「失敗」的錯誤消息框

Index.cshtml

<script src="~/Scripts/jquery-1.8.2.min.js"></script> 
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script> 
<h2>Files Upload</h2> 
<script type="text/javascript"> 
$(function() { 
    $("#form0").submit(function(event) { 
     var dataString; 
     event.preventDefault(); 
     var action = $("#form0").attr("action"); 
     if ($("#form0").attr("enctype") == "multipart/form-data") { 
      //this only works in some browsers. 
      //purpose? to submit files over ajax. because screw iframes. 
      //also, we need to call .get(0) on the jQuery element to turn it into a regular DOM element so that FormData can use it. 
      dataString = new FormData($("#form0").get(0)); 
      contentType = false; 
      processData = false; 
     } else { 
      // regular form, do your own thing if you need it 
     } 
     $.ajax({ 
      type: "POST", 
      url: action, 
      data: dataString, 
      dataType: "json", //change to your own, else read my note above on enabling the JsonValueProviderFactory in MVC 
      contentType: contentType, 
      processData: processData, 
      success: function(data) { 
       //BTW, data is one of the worst names you can make for a variable 

      }, 
      error: function(jqXHR, textStatus, errorThrown) { 
       //do your own thing 
       alert("fail"); 
      } 
     }); 
    }); //end .submit() 
}); 
</script> 
<div id="uploadDiv"> 
@Html.Action("Files", "Home") 
</div> 

@using (Ajax.BeginForm("Files", "Home", new AjaxOptions { UpdateTargetId = "uploadDiv", HttpMethod = "Post" }, new { enctype = "multipart/form-data", @id="form0"})) 
{ 
<div> 
    <div>Upload new file: 
     <input type="file" name="file" /></div> 
    <input type="submit" value="Save" /> 
</div> 
} 
<br /> 

控制器

public PartialViewResult Files(HttpPostedFileBase file) 
    { 
     IEnumerable<string> files; 
     if ((file != null) && (file.ContentLength > 0)) 
     { 
      string fileName = file.FileName; 
      string saveLocation = @"D:\Files"; 
      string fullFilePath = Path.Combine(saveLocation, fileName);    


      try 
      { 
       file.SaveAs(fullFilePath); 
       FileInfo fileInfo = new FileInfo(fullFilePath); 
       file.InputStream.Read(new byte[fileInfo.Length], 0, file.ContentLength);      
      } 
      catch (Exception e) 
      { 
       TempData["FileUpload"] = e.Message; 
       return PartialView(); 
      } 
      files = Directory.GetFiles(@"D:\Files\"); 
      return PartialView(files); 
     } 
     else 
     { 
      files = Directory.GetFiles(@"D:\Files\"); 
      return PartialView(files); 
     } 
    } 

Files.cshtml

@model IEnumerable<string> 

@foreach (string f in Model) 
{ 
<p>@f</p> 
} 

的Global.asax

ValueProviderFactories.Factories.Add(new JsonValueProviderFactory()); 
+0

我寫了這樣的一篇博客文章而回 - 可能幫助你: http://blog.shadowmoses.co.uk/2013/06/handling-uploads-with-mvc4-jquery.html – Spikeh

+0

您在Ajax.BeginForm方法中缺少路徑值。 – hakan

回答

64

這是複雜更好地使用jquery forms plugin

下面是示例:

Html.BeginForm

@using (Html.BeginForm("YourAction", "YourController")) 
{ 
    @Html.AntiForgeryToken() 
    <input type="file" name="files"><br> 
    <input type="submit" value="Upload File to Server"> 
} 

操作方法

[HttpPost] 
    [ValidateAntiForgeryToken] 
    public void YourAction(IEnumerable<HttpPostedFileBase> files) 
    { 
     if (files != null) 
     { 
      foreach (var file in files) 
      { 
       // Verify that the user selected a file 
       if (file != null && file.ContentLength > 0) 
       { 
        // extract only the fielname 
        var fileName = Path.GetFileName(file.FileName); 
        // TODO: need to define destination 
        var path = Path.Combine(Server.MapPath("~/Upload"), fileName); 
        file.SaveAs(path); 
       } 
      } 
     } 
    } 

進度條

<div class="progress progress-striped"> 
    <div class="progress-bar progress-bar-success">0%</div> 
</div> 

Jquery的&表腳本

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script> 
<script src="http://malsup.github.com/jquery.form.js"></script> 

<script> 
(function() { 

var bar = $('.progress-bar'); 
var percent = $('.progress-bar'); 
var status = $('#status'); 

$('form').ajaxForm({ 
    beforeSend: function() { 
     status.empty(); 
     var percentVal = '0%'; 
     bar.width(percentVal) 
     percent.html(percentVal); 
    }, 
    uploadProgress: function(event, position, total, percentComplete) { 
     var percentVal = percentComplete + '%'; 
     bar.width(percentVal) 
     percent.html(percentVal); 
    }, 
    success: function() { 
     var percentVal = '100%'; 
     bar.width(percentVal) 
     percent.html(percentVal); 
    }, 
    complete: function(xhr) { 
     status.html(xhr.responseText); 
    } 
}); 

})();  
</script> 

更新...

的人誰也越來越調用操作方法兩次的問題是由於Ajax.BeginForm,只需將其轉換爲HTML .BeginForm()。 欲瞭解更多信息並下載示例代碼,請參閱this blog

+0

它適用於所有瀏覽器,但IE –

+2

嘗試添加dataType:'json', type:「POST」, contentType:「application/json」 in $('form')。ajaxForm(); –

+0

在IE文件中添加此代碼後,uploder被禁用 – Haris

4

Ashwini Verma的答案几乎是正確的,但它有一個缺點,表單提交兩次。

這是由於使用Ajax.BeginForm()造成的。使用Html.BeginForm()將解決它。

下面是一個例子:

@* do not use Ajax.BeginForm() as it would cause the form to submit twice in connection with jQuery.Form *@ 
@using (var lForm = Html.BeginForm( 
    <ActionName>, <ControllerName>, FormMethod.Post, 
    new Dictionary<string, object> {{"name", <YourFormName>}, {"enctype", "multipart/form-data"}})) 
{ 
+0

你說得對。它發送表單兩次,但如何使用Html.BeginForm()並將UpdateTargetId? – kavain

+0

@kavain查看由Ajax.BeginForm()生成的HTML代碼並將其應用於Html.BeginForm()調用。它基本上都是由jQuery Ajax Unobtrusive插件解析的所有HTML標籤屬性。因此,如果確保更新目標的屬性正確生成,那麼目標更新也應該起作用。 – ViRuSTriNiTy

0

您需要HTML5文件處理和對客戶端讀取文件內容來獲得base64編碼數據。

在客戶端,你必須把:

<div> 
     @Html.HiddenFor(m => m.AttachmentFileName) 
     @Html.HiddenFor(m => m.AttachmentFileSize) 
     @Html.HiddenFor(m => m.AttachmentFileType) 
     @Html.HiddenFor(m => m.AttachmentFileContentsBase64) 

    <input type="file" name="AttachmentFile" id="AttachmentFile" onchange="handleAttachmentFileChange(this.files)" /> 
    @Html.ValidationMessageFor(m => m.AttachmentFile) 
</div> 

<script> 
    function handleAttachmentFileChange(files) { 
     var file = files[0]; 
     $("#AttachmentFileName").val(file.name); 
     $("#AttachmentFileSize").val(file.size); 
     $("#AttachmentFileType").val(file.type || "application/octet-stream"); 

     var fileReader = new FileReader(); 
     fileReader.onload = function() { 
      fileReader.result; 

      $("#AttachmentFileContentsBase64").val(fileReader.result); 
     }; 
     fileReader.readAsDataURL(file); 
    }; 
</script> 

所以,你的代碼將填充文件數據(文件名,類型,大小,base64編碼的內容)隱藏字段。 而在服務器端,您放:需要與你的模型和邏輯進行修改

  if (AttachmentFileSize > 0) 
      { 
       string fileName = AttachmentFileName.Contains("\\") ? AttachmentFileName.Substring(AttachmentFileName.LastIndexOf("\\") + 1) : AttachmentFileName; 

       byte[] fileBytes = Convert.FromBase64String(AttachmentFileContentsBase64.Substring(AttachmentFileContentsBase64.IndexOf(',') + 1)); 

//save file to file system or db 

       ModelState.Remove("CurrentAttachmentFileId"); 
       ModelState.Remove("CurrentAttachmentFileName"); 

      } 
      else if (AttachmentFileSize == -1) 
      { 
//remove existing file from fs or db 
      } 

的代碼,但它爲我工作