¿Cuál es la diferencia entre los cuatro resultados de archivo en ASP.NET MVC

136

ASP.NET tiene cuatro tipos diferentes de resultados de archivos:

  • FileContentResult: envía el contenido de un archivo binario a la respuesta.
  • FilePathResult: envía el contenido de un archivo a la respuesta
  • FileResult: devuelve la salida binaria para escribir en la respuesta
  • FileStreamResult: envía contenido binario a la respuesta mediante una instancia de Stream

Esas descripciones son tomadas de MSDN y, con la excepción de FileStreamResult, los primeros tres suenan idénticos. Entonces, ¿cuál es la diferencia entre ellos?

Robert MacLean
fuente

Respuestas:

176

FileResult es una clase base abstracta para todos los demás.

  • FileContentResult - lo usa cuando tiene una matriz de bytes que desea devolver como un archivo
  • FilePathResult - cuando tiene un archivo en el disco y desea devolver su contenido (proporciona una ruta)
  • FileStreamResult - tiene una transmisión abierta, desea devolver su contenido como un archivo

Sin embargo, rara vez tendrá que usar estas clases: puede usar una de las Controller.Filesobrecargas y dejar que ASP.NET MVC haga la magia por usted.

maciejkow
fuente
29

Gran pregunta ... y merece más detalles. Me encuentro aquí como resultado de una situación interesante. Estábamos entregando algunos archivos adjuntos en PDF a través del entorno MVC3 / C #. Nuestro código se lanzó y comenzamos a recibir algunas respuestas de nuestros clientes de que las descargas se comportaban de manera extraña cuando usaban Chrome y que el tipo de archivo se convertía a 'pdf-, attach.pdf-, adjunto'. Sí ... lo tienes ... todo. Entonces, uno podría reescribirlo para que solo sea 'pdf' y el archivo aún se guardaría intacto, ¡pero qué desastre!

Entonces, para describir la situación inicial, estábamos configurando el encabezado 'Content-Disposition' y luego devolviendo un FileContentResult ...

var cd = new System.Net.Mime.ContentDisposition
            {
                FileName = result.Attachment.FileName,
                Inline = false
            };
            Response.AppendHeader("Content-Disposition", cd.ToString());

return File(result.Attachment.Data, MimeExtensionHelper.GetMimeType(result.Attachment.FileName), result.Attachment.FileName);

Parecía bueno Funcionó bien en IE. Así que investigué un poco e intenté implementar FileStreamResult en su lugar (manteniendo el configurador Content-Disposition):

MemoryStream dataStream = new MemoryStream();
dataStream.Write(result.Attachment.Data, 0, result.Attachment.Data.Length);
dataStream.Position = 0;
return new FileStreamResult(dataStream, MimeExtensionHelper.GetMimeType(result.Attachment.FileName));

Se solucionó el problema en Chrome! Hmmm ... pero ¿por qué debería tener que tomar mi matriz de bytes perfectamente buena y transmitirla y luego devolverla a través de esto para que el nombre del archivo funcione correctamente?

Luego vino el violinista.

Con FileContentResult, obtuve 2 Disposiciones de contenido en el encabezado. Con FileStreamResult, obtuve 1.

FileContentResult agrega un encabezado Content-Disposition al proporcionar el Nombre del archivo y Chrome considera que los múltiplos de este encabezado son un error.

Reacción extraña ... pero definitivamente una que es bueno saber.

beauXjames
fuente
3
Solo un consejo, en .NET 4+ puedes usar System.Web.MimeMapping.GetMimeMapping(filename)para recopilar el tipo mime si no puedes acceder a él fácilmente.
GONeale
44
Proporcionar un nombre de archivo a un Fileresultado significa establecer su FileDownloadNamepropiedad, que establece los Content-Dispositionencabezados por usted. Y admite correctamente los nombres de archivo utf-8, que no son de ContentDispositionclase auxiliar (consulte mi comentario aquí para obtener más detalles).
Frédéric
1
Sí, gracias @ Frédéric, ¡solo tú de todas las publicaciones SO me has explicado lo que estaba pasando!
Nacht