Ajax.BeginForm en MVC para cargar archivos

Estaba tratando de usar un ejemplo que se menciona aquí. ¿Cómo hacer una publicación de formulario ASP.NET MVC Ajax con multipart / form-data?

Pero sigo obteniendo el cuadro de mensaje de error “fail”

Index.cshtml

  

Files Upload

$(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() });
@Html.Action("Files", "Home")
@using (Ajax.BeginForm("Files", "Home", new AjaxOptions { UpdateTargetId = "uploadDiv", HttpMethod = "Post" }, new { enctype = "multipart/form-data", @id="form0"})) {
Upload new file:
}

Controlador

 public PartialViewResult Files(HttpPostedFileBase file) { IEnumerable 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 @foreach (string f in Model) { 

@f

}

Global.asax

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

Eso es un mejor uso del plugin de formas jquery .

Aquí está la muestra:

Html.BeginForm

  @using (Html.BeginForm("YourAction", "YourController")) { @Html.AntiForgeryToken() 
}

Método de acción

  [HttpPost] [ValidateAntiForgeryToken] public void YourAction(IEnumerable 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); } } } } 

Barra de progreso

 
0%

Guión Jquery & Form

    

Actualizar…

Las personas que obtienen el problema del método de acción de llamada dos veces se deben a Ajax.BeginForm, simplemente conviértanlo a Html.BeginForm (). Para obtener más aclaraciones y descargar el código de muestra, consulte en este blog .

La respuesta de Ashwini Verma es casi correcta, pero tiene un inconveniente, el formulario se envía dos veces.

Esto es causado por el uso de Ajax.BeginForm() . Usar Html.BeginForm() lo arreglará.

Aquí hay un ejemplo:

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

Necesita manejo de archivos html5 y leer los contenidos del archivo en el cliente para obtener datos codificados en base64.

En el cliente tienes que poner:

 
@Html.HiddenFor(m => m.AttachmentFileName) @Html.HiddenFor(m => m.AttachmentFileSize) @Html.HiddenFor(m => m.AttachmentFileType) @Html.HiddenFor(m => m.AttachmentFileContentsBase64) @Html.ValidationMessageFor(m => m.AttachmentFile)

Por lo tanto, su código llenará los campos ocultos con los datos del archivo (nombre del archivo, tipo, tamaño, contenido codificado en base64). Y en el lado del servidor pones:

  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 } 

El código debe ser modificado con tus modelos y tu lógica, pero funcionó para mí