Потоковый файл с использованием 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 54

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?

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; 
     } 
}