Потоковый файл с использованием ASP.NET MVC FileContentResult в браузере с именем?
есть ли способ потоковой передачи файла с помощью ASP.NET MVC FileContentResult в браузере с определенным именем?
Я заметил, что вы можете либо иметь FileDialog (Open/Save), либо вы можете передавать файл в окне браузера, но тогда он будет использовать имя действия при попытке сохранить файл.
У меня есть следующий сценарий:
byte[] contents = DocumentServiceInstance.CreateDocument(orderId, EPrintTypes.Quote);
result = File(contents, "application/pdf", String.Format("Quote{0}.pdf", orderId));
когда я использую это, я могу передавать байты, но диалог открытия/сохранения файла предоставляется пользователю. Я хотел бы на самом деле поток этот файл в окне браузера.
Если я просто использую FilePathResult, он показывает файл в окне браузера, но затем, когда я нажимаю кнопку "СОХРАНИТЬ", чтобы сохранить файл в PDF, он показывает мне имя действия в качестве имени файла.
кто-нибудь сталкивался с этим?
6 ответов:
public ActionResult Index() { byte[] contents = FetchPdfBytes(); return File(contents, "application/pdf", "test.pdf"); }
и для открытия PDF внутри браузера вам нужно будет установить :
public ActionResult Index() { byte[] contents = FetchPdfBytes(); Response.AddHeader("Content-Disposition", "inline; filename=test.pdf"); return File(contents, "application/pdf"); }
на самом деле, самый простой способ-это сделать следующее...
byte[] content = your_byte[]; FileContentResult result = new FileContentResult(content, "application/octet-stream") { FileDownloadName = "your_file_name" }; return result;
Это может быть полезно для любого, кто сталкивается с этой проблемой. Я наконец-то нашел решение. Оказывается, даже если мы используем inline для "Content-disposition" и указываем имя файла, браузеры все равно не используют имя файла. Вместо этого браузеры пытаются интерпретировать имя файла на основе пути / URL.
вы можете прочитать дальше по этому URL: безопасно скачать файл внутри браузера с правильным именем
Это дало мне идею, я только что создал свой URL маршрут, который преобразует URL-адрес и заканчивает его именем файла, который я хотел дать файлу. Так, например, мой оригинальный вызов контроллера просто состоял из передачи идентификатора заказа печатаемого заказа. Я ожидал, что имя файла в формате{0}.pdf, где {0} - идентификатор заказа. Аналогично для цитат, я хотел цитату{0}.документ pdf.
в моем контроллере, я просто пошел вперед и добавил дополнительный параметр, чтобы принять имя файла. Я передал имя файла в качестве параметра в поле URL-АДРЕС.Метод действия.
затем я создал новый маршрут, который сопоставил бы этот URL-адрес с форматом: http://localhost/ShoppingCart/PrintQuote/1054/Quote1054.pdf
routes.MapRoute("", "{controller}/{action}/{orderId}/{fileName}", new { controller = "ShoppingCart", action = "PrintQuote" } , new string[] { "x.x.x.Controllers" } );
это в значительной степени решило мою проблему. Надеюсь, это кому-то поможет!
Cheerz, Ануп
предыдущие ответы верны: добавление линии...
Response.AddHeader("Content-Disposition", "inline; filename=[filename]");
...приведет к тому, что несколько заголовков размещения контента будут отправлены в браузер. Это происходит b / c
FileContentResult
внутренне применяет заголовок, Если вы предоставляете ему имя файла. Альтернативным и довольно простым решением является простое создание подклассаFileContentResult
и переопределить егоExecuteResult()
метод. Вот пример, который создает экземплярSystem.Net.Mime.ContentDisposition
класс (тот же объект, который используется во внутреннемFileContentResult
реализация) и передает его в новый класс: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); } }
в своем
Controller
, или вController
, вы можете написать простой помощник для создания экземпляраFileContentResultWithContentDisposition
а затем вызвать его из вашего метода действий, например: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 }); }
теперь файл будет отправлен в браузер с выбранным именем файла и с заголовком content-disposition "inline; filename=[filename]".
Я надеюсь, что помогает!
абсолютный самый простой способ передать файл в браузер с помощью ASP.NET MVC это:
public ActionResult DownloadFile() { return File(@"c:\path\to\somefile.pdf", "application/pdf", "Your Filename.pdf"); }
Это проще, чем метод, предложенный @azarc3, так как вам даже не нужно читать байты.
кредит идет на: http://prideparrot.com/blog/archive/2012/8/uploading_and_returning_files#how_to_return_a_file_as_response
* * Edit**
по-видимому, мой "ответ" совпадает с вопросом OP. Но я не проблема у него есть. Вероятно, это была проблема со старой версией ASP.NET MVC?