2012-06-10 9 views
31

Estoy cargando archivos utilizando ASP.NET Web API. He hecho esto antes del RC, pero por alguna razón el archivo se guarda como "BodyPart_3ded2bfb-40be-4183-b789-9301f93e90af" en lugar del nombre del archivo. La variable de nombre de archivo a continuación también devuelve esta cadena de partes del cuerpo en lugar del nombre del archivo. Parece que no puedo descubrir dónde me estoy equivocando. Cualquier ayuda es apreciada.ASP.NET Web API Archivo guardado como "BodyPart_3ded2bfb-40be-4183-b789-9301f93e90af"

El código de cliente:

function upload() { 
    $("#divResult").html("Uploading..."); 
    var formData = new FormData($('form')[0]); 
    $.ajax({ 
     url: 'api/files/uploadfile?folder=' + $('#ddlFolders').val(), 
     type: 'POST', 
     success: function (data) { 
      $("#divResult").html(data); 
     }, 
     data: formData, 
     cache: false, 
     contentType: false, 
     processData: false 
    }); 
}; 

controlador:

public Task<HttpResponseMessage> UploadFile([FromUri]string folder) 
    { 
     if (!Request.Content.IsMimeMultipartContent()) 
     { 
      throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.UnsupportedMediaType)); 
     } 

     // Save file 
     MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/Files")); 
     Task<IEnumerable<HttpContent>> task = Request.Content.ReadAsMultipartAsync(provider); 

     return task.ContinueWith<HttpResponseMessage>(contents => 
     { 
      string filename = provider.BodyPartFileNames.First().Value; 
      return new HttpResponseMessage() 
      { 
       Content = new StringContent(string.Format("File saved in {0}.", folder)) 
      }; 

     }, TaskScheduler.FromCurrentSynchronizationContext()); 

Los archivos están buscando como:

enter image description here

+0

escribí mi ejemplo completo aquí: http://rivdiv.wordpress.com/2012/06/13/uploading-a-file-using-asp-net-web-api/ – Rivka

Respuesta

44

Eso fue un cambio consciente hicimos - se consideró un riesgo de seguridad para tomar el nombre del archivo provisto en el Contenido-Dispositivos en el campo de encabezado y, en su lugar, ahora calculamos un nombre de archivo que es lo que está viendo.

Si desea controlar el nombre del archivo local del servidor usted mismo, puede derivar de MultipartFormDataStreamProvider y anular GetLocalFileName para proporcionar el nombre que desee. Sin embargo, tenga en cuenta que puede haber consideraciones de seguridad al hacerlo.

Espero que esto ayude,

Henrik

+3

Gracias por su respuesta. ¿Cómo guardo el archivo real correctamente? En este momento es del tipo de datos "Archivo" sin extensión y no se puede abrir. – Rivka

+4

Encontré una solución temporal por ahora - para usar File.Move y agregar la extensión correcta usando * provider.BodyPartFileNames.FirstOrDefault(). Key.TrimStart ('"'). TrimEnd ('"') * para obtener el nombre original del archivo. Esto se siente un poco hacia atrás sin embargo. Agradecería cualquier iluminación. Gracias. – Rivka

+1

clase pública FormDataStreamer: MultipartFormDataStreamProvider { FormDataStreamer pública (ROOTPATH ​​cadena): base (ROOTPATH) {} FormDataStreamer pública (cadena ROOTPATH, int bufferSize): base (ROOTPATH, bufferSize) {} cadena public override GetLocalFileName (HttpContentHeaders cabeceras) {var srcFileName = headers.ContentDisposition.FileName.Replace ("\"", ""); retorno Guid.NewGuid() + Path.GetExtension (srcFileName); }} –

16

que actualiza el código para el tutorial para que funcione con RC API Web ASP.NET. De hecho, como Henrik mencionó Content-Disposition, ya no se usa un nombre de archivo. Consulte los archivos de origen en la parte inferior de la publicación - http://www.strathweb.com/2012/04/html5-drag-and-drop-asynchronous-multi-file-upload-with-asp-net-webapi/

Tenga en cuenta que hay más cambios en MultipartFormDataStreamProvider que no hicieron el corte en el RC, por lo que ahora es aún más flexible. Henrik escribió en su blog sobre los aquí - http://blogs.msdn.com/b/henrikn/archive/2012/04/27/asp-net-web-api-updates-april-27.aspx.

EDIT: he blogged acerca manera nueva y mejorada de la carga de archivos en RTM Web API, por lo que debe de esperar ayuda llegue cosas organizadas - http://www.strathweb.com/2012/08/a-guide-to-asynchronous-file-uploads-in-asp-net-web-api-rtm/

+0

Gracias, tu ejemplo es fácil de leer y seguir. Yo había escrito el mío usando el código beta Me estaba tirando de los pelos tratando de descubrir cómo hacerlo en el RC. – Keith

+0

Gracias Filip. Así que supongo que la forma correcta * es * de obtener el archivo original de la clave y luego mover/renombrar el archivo. No me encontré con ningún artículo de API web que tuviera este cambio particular de RC especificado, me alegro de haber puesto esta pregunta por ahí. Gracias. – Rivka

+0

Esto es simplemente hermoso. ¡Funciona de maravilla! – Detilium

7

Aquí, este trabajo para mí

En controlador API

// We implement MultipartFormDataStreamProvider to override the filename of File which 
// will be stored on server, or else the default name will be of the format like Body- 
// Part_{GUID}. In the following implementation we simply get the FileName from 
// ContentDisposition Header of the Request Body. 
public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider 
{ 
    public CustomMultipartFormDataStreamProvider(string path) : base(path) { } 

    public override string GetLocalFileName(HttpContentHeaders headers) 
    { 
     return headers.ContentDisposition.FileName.Replace("\"", string.Empty); 
    } 
} 

Entonces

string root = HttpContext.Current.Server.MapPath("~/App_Data");  
CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(root); 

Gracias,