Transmitir archivos usando ASP.NET MVC FileContentResult en un navegador con un nombre?
asp.net-mvc fileresult (6)
¿Hay alguna manera de transmitir un archivo usando ASP.NET MVC FileContentResult dentro del navegador con un nombre específico?
Me di cuenta de que puede tener un FileDialog (Abrir / Guardar) o puede transmitir el archivo en una ventana del navegador, pero luego usará el ActionName cuando intente guardar el archivo.
Tengo el siguiente escenario:
byte[] contents = DocumentServiceInstance.CreateDocument(orderId, EPrintTypes.Quote);
result = File(contents, "application/pdf", String.Format("Quote{0}.pdf", orderId));
Cuando uso esto, puedo transmitir los bytes, pero se le da un diálogo de archivo ABRIR / GUARDAR al usuario. Me gustaría transmitir este archivo en una ventana del navegador.
Si solo uso FilePathResult, muestra el archivo en una ventana del navegador, pero cuando hago clic en el botón "Guardar" para guardar el archivo en PDF, me muestra el nombre de la acción como el nombre del archivo.
¿Alguien ha encontrado esto?
En realidad, la forma más sencilla es hacer lo siguiente ...
byte[] content = your_byte[];
FileContentResult result = new FileContentResult(content, "application/octet-stream")
{
FileDownloadName = "your_file_name"
};
return result;
Esto podría ser útil para quien más se enfrenta a este problema. Finalmente descubrí una solución. Resulta que, incluso si usamos el en línea para "disposición de contenido" y especificamos un nombre de archivo, los navegadores aún no usan el nombre del archivo. En cambio, los navegadores intentan interpretar el nombre del archivo en función de la ruta / URL.
Puede leer más en esta URL: descargar el archivo en el navegador con el nombre de archivo correcto
Esto me dio una idea, acabo de crear mi ruta de URL que convertiría la URL y la terminaría con el nombre del archivo que quería dar al archivo. Entonces, por ejemplo, mi llamada de controlador original solo consistía en pasar el Id de pedido de la orden que se imprimía. Esperaba que el nombre del archivo fuera del formato Order {0} .pdf donde {0} es el ID del pedido. Del mismo modo para las comillas, quería Cita {0} .pdf.
En mi controlador, simplemente seguí adelante y agregué un parámetro adicional para aceptar el nombre del archivo. Pasé el nombre del archivo como parámetro en el método URL.Action.
Luego creé una nueva ruta que mapearía esa URL al formato: http://localhost/ShoppingCart/PrintQuote/1054/Quote1054.pdf
routes.MapRoute("", "{controller}/{action}/{orderId}/{fileName}",
new { controller = "ShoppingCart", action = "PrintQuote" }
, new string[] { "x.x.x.Controllers" }
);
Esto prácticamente solucionó mi problema. ¡Espero que esto ayude a alguien!
Cheerz, Anup
La forma más sencilla de transmitir un archivo al navegador utilizando ASP.NET MVC es esta:
public ActionResult DownloadFile() {
return File(@"c:/path/to/somefile.pdf", "application/pdf", "Your Filename.pdf");
}
Esto es más fácil que el método sugerido por @ azarc3 ya que ni siquiera necesita leer los bytes.
El crédito va a: http://prideparrot.com/blog/archive/2012/8/uploading_and_returning_files#how_to_return_a_file_as_response
** Editar **
Aparentemente, mi ''respuesta'' es la misma que la pregunta del OP. Pero no estoy enfrentando el problema que está teniendo. Probablemente este era un problema con la versión anterior de ASP.NET MVC?
Las respuestas anteriores son correctas: agregar la línea ...
Response.AddHeader("Content-Disposition", "inline; filename=[filename]");
... provocará que múltiples encabezados Content-Disposition sean enviados al navegador. Esto sucede b / c FileContentResult
internamente aplica el encabezado si le proporciona un nombre de archivo. Una solución alternativa, y bastante simple, es simplemente crear una subclase de FileContentResult
y anular su método ExecuteResult()
. Aquí hay un ejemplo que ejemplifica una instancia de la clase System.Net.Mime.ContentDisposition
(el mismo objeto utilizado en la implementación interna FileContentResult
) y la pasa a la nueva clase:
public class FileContentResultWithContentDisposition : FileContentResult
{
private const string ContentDispositionHeaderName = "Content-Disposition";
public FileContentResultWithContentDisposition(byte[] fileContents, string contentType, ContentDisposition contentDisposition)
: base(fileContents, contentType)
{
// check for null or invalid ctor arguments
ContentDisposition = contentDisposition;
}
public ContentDisposition ContentDisposition { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
// check for null or invalid method argument
ContentDisposition.FileName = ContentDisposition.FileName ?? FileDownloadName;
var response = context.HttpContext.Response;
response.ContentType = ContentType;
response.AddHeader(ContentDispositionHeaderName, ContentDisposition.ToString());
WriteFile(response);
}
}
En su Controller
, o en un Controller
base, puede escribir un asistente simple para crear una instancia de FileContentResultWithContentDisposition
y luego llamarlo desde su método de acción, de esta manera:
protected virtual FileContentResult File(byte[] fileContents, string contentType, ContentDisposition contentDisposition)
{
var result = new FileContentResultWithContentDisposition(fileContents, contentType, contentDisposition);
return result;
}
public ActionResult Report()
{
// get a reference to your document or file
// in this example the report exposes properties for
// the byte[] data and content-type of the document
var report = ...
return File(report.Data, report.ContentType, new ContentDisposition {
Inline = true,
FileName = report.FileName
});
}
Ahora el archivo se enviará al navegador con el nombre de archivo que elija y con un encabezado de disposición de contenido de "inline; filename = [filename]".
¡Espero que eso ayude!
public ActionResult Index()
{
byte[] contents = FetchPdfBytes();
return File(contents, "application/pdf", "test.pdf");
}
y para abrir el PDF dentro del navegador, deberá configurar el encabezado Content-Disposition
:
public ActionResult Index()
{
byte[] contents = FetchPdfBytes();
Response.AddHeader("Content-Disposition", "inline; filename=test.pdf");
return File(contents, "application/pdf");
}
public FileContentResult GetImage(int productId) {
Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId);
if (prod != null) {
return File(prod.ImageData, prod.ImageMimeType);
} else {
return null;
}
}