2010-09-13 5 views
9

Estoy intentando utilizar la secuencia de comandos se han encontrado vuelos http://valums.com/ajax-upload/necesita ayuda para la depuración basada en XHR Ajax imagen Subir con ASP.NET MVC2

Mi controlador es el siguiente

using System; 
using System.IO; 
using System.Text.RegularExpressions; 
using System.Web; 
using System.Web.Hosting; 
using System.Web.Mvc; 
using MHNHub.Areas.ViewModels; 
using MHNHub.Models; 
using MHNHub.ViewModels; 

namespace MHNHub.Areas.Admin.Controllers 
{ 
    [Authorize(Roles = "Administrator")] 
    public class ImageController : Controller 
    { 

     private MHNHubEntities _entities = new MHNHubEntities(); 

     // 
     // GET: /Image/ 
     [AcceptVerbs(HttpVerbs.Get)] 
     public ActionResult ImageUploader() 
     { 
      var viewModel = new ImageViewModel() 
      { 
       Image = new Image() 
      }; 

      return PartialView(viewModel); 
     } 

     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult ImageUploader(Image image) 
     { 
      try 
      { 
       _entities.Images.AddObject(image); 
       _entities.SaveChanges(); 

       return RedirectToAction("Index", "Product"); 
      } 
      catch (Exception ex) 
      { 
       var viewModel = new ImageViewModel() 
           { 
            Image = image, 
            HasError = true, 
            ErrorMessage = ex.Message 
           }; 
       return PartialView(viewModel); 

      } 
     } 

     private string _uploadsFolder = HostingEnvironment.MapPath("~/App_Data/Files"); 

     public Guid Upload(HttpPostedFileBase fileBase) 
     { 
      var identifier = Guid.NewGuid(); 
      fileBase.SaveAs(GetDiskLocation(identifier)); 
      return identifier; 
     } 

     private string GetDiskLocation(Guid identifier) 
     { 
      return Path.Combine(_uploadsFolder, identifier.ToString()); 
     } 

    } 

} 

y tengo una vista parcial como esto

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MHNHub.ViewModels.ImageViewModel>" %> 

<script type="text/javascript"> 
    $(function() { 
     $("#imagedialog").dialog({ 
      bgiframe: true, 
      height: 170, 
      width: 430, 
      modal: true, 
      autoOpen: false, 
      resizable: true 
     }) 
    }); 

    $(document).ready(function createUploader() { 
     var uploader = new qq.FileUploader({ 
      element: document.getElementById('fileuploader'), 
      action: '/Image/Upload/', 
      name: 'name' 
     }); 

    }); 

</script>  

<div id="imagedialog" title="Upload Image"> 

       <div id="fileuploader"> 

       </div> 
       <h6>Drag and drop files supported in Firefox and Google Chrome with javascript enabled.</h6> 
        <noscript> 
         <form action="/image/upload" enctype="multipart/form-data" method="post"> 
          Select a file: <input type="file" name="photo" id="photo" /> 

          <input type="submit" value="Upload" name="submit"/> 
         </form> 
        </noscript> 


</div> 

<div class="editor-field"> 
    <img src="<%: Model.Image.FileName %>" /> 
    <%: Html.TextBoxFor(model => model.Image.FileName) %> 
    <%: Html.ValidationMessageFor(model => model.Image.FileName)%> 
    <a href="#" onclick="jQuery('#imagedialog').dialog('open'); return false">Upload Image</a> 
</div> 

tengo fileuploader.js y fileuploader.css vinculados correctamente en la página principal, y el cargador aparece correctamente, y es incluso llamar a mi acción, pero el Http PublicadaFileBase es nula y la acción de carga arroja una excepción. ¿Alguna idea de lo que debería hacer?

Editar

Así que he descubierto el uso de Firebug que su envío de un XmlHttpRequest. ¿Cómo manejo esto en mi acción de carga?

Respuesta

9

La razón por la que obtiene un parámetro vacío en la acción de su controlador es porque este complemento no envía una solicitud multipart/form-data al servidor. En su lugar, envía el encabezado de solicitud de tipo de contenido application/octet-stream y escribe el contenido del archivo directamente en la secuencia de solicitud, agregando un parámetro ?qqfile a la URL que contiene el nombre del archivo. Así que si desea recuperar este en el controlador tendrá que leer directamente la corriente:

[HttpPost] 
public ActionResult Upload(string qqfile) 
{ 
    using (var reader = new BinaryReader(Request.InputStream)) 
    { 
     // This will contain the uploaded file data and the qqfile the name 
     byte[] file = reader.ReadBytes((int)Request.InputStream.Length); 
    } 
    return View(); 
} 

Si selecciona varios archivos el plugin simplemente envía múltiples peticiones al servidor para que esto funcione.

Además, si desea manejar archivos mayores que int.MaxValue tendrá que leer de la corriente pedido en trozos y escribir directamente a un flujo de salida en lugar de cargar todo el archivo en un búfer de memoria:

using (var outputStream = File.Create(qqfile)) 
{ 
    const int chunkSize = 2 * 1024; // 2KB 
    byte[] buffer = new byte[chunkSize]; 
    int bytesRead; 
    while ((bytesRead = Request.InputStream.Read(buffer, 0, buffer.Length)) > 0) 
    { 
     outputStream.Write(buffer, 0, bytesRead); 
    } 
} 

Observación: elimine el nombre de la función createUploader de su document.ready. Debería ser una función anónima allí. Incluso podría fusionarlo con el $(function() { ... }); que ya tiene para configurar el cuadro de diálogo modal.

+0

¿Cómo guardo el archivo (que siempre será una imagen), por ejemplo, en app_data/uploads o algo así? – Gallen

+0

Eso es lo que hace mi segundo fragmento. Solo necesita especificar la ruta en 'File.Create'. –

+0

Gracias Darin, está guardando los archivos ahora. Solo una cosa más: ¿cómo mantengo el tipo de contenido? Me gusta subir un .jpg guarda como .jpg, etc. En lugar de solo como un archivo. – Gallen

Cuestiones relacionadas