Яка різниця між чотирма результатами файлів у ASP.NET MVC


136

ASP.NET має чотири різні типи файлів:

  • FileContentResult: надсилає вміст бінарного файлу до відповіді.
  • FilePathResult: надсилає вміст файлу до відповіді
  • FileResult: Повертає двійковий вихід для запису у відповідь
  • FileStreamResult: надсилає бінарний вміст відповіді за допомогою екземпляра Stream

Ці описи взяті з MSDN і, за винятком FileStreamResult, перші три звуки однакові. То яка різниця між ними?

Відповіді:


176

FileResult є абстрактним базовим класом для всіх інших.

  • FileContentResult - ви використовуєте його, коли у вас є байтовий масив, який ви хочете повернути як файл
  • FilePathResult - коли у вас є файл на диску і ви хочете повернути його вміст (ви даєте шлях)
  • FileStreamResult - у вас відкритий потік, ви хочете повернути його вміст у вигляді файлу

Однак, вам рідко доведеться використовувати ці класи - ви можете просто скористатися однією з Controller.Fileперевантажень і дозволити ASP.NET MVC зробити магію за вас.


29

Відмінне запитання ... і заслуговує на більше деталей. Я опиняюся тут внаслідок цікавої ситуації. Ми доставляли деякі вкладені файли у форматі PDF через середовище MVC3 / C #. Наш код було випущено, і ми почали отримувати відповіді від наших клієнтів про те, що завантаження поводилися дивно, коли вони використовували Chrome, а тип файлу перетворювався на "pdf-, attachment.pdf-, attachment". Так ... ти зрозумів ... вся справа. Отже, можна переписати його просто на "pdf", і файл все одно збереже недоторканим, але який безлад!

Отже, щоб описати початкову ситуацію, ми встановлювали заголовок 'Content-Disposition', а потім повертаємо 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);

Здавалося, добре. Добре працював в IE. Тож я зробив кілька досліджень і спробував натомість застосувати FileStreamResult (зберігаючи налаштування 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));

Він вирішив проблему в Chrome! Хм-м-м ... але чому в біса треба взяти свій ідеально хороший байтовий масив і передати його, а потім повернути через це, щоб ім'я файлу працювало правильно?

Потім прийшов Фіддлер.

За допомогою FileContentResult я отримав 2 заголовки вмісту у заголовку. З FileStreamResult я отримав 1.

FileContentResult додає заголовок Content-Disposition, коли надає Ім'я файлу, а Chrome розглядає кратність цього заголовка як помилку.

Дивна реакція ... але, безумовно, таку, яку добре знати.


3
Лише підказка, в .NET 4+ ви можете використовувати System.Web.MimeMapping.GetMimeMapping(filename)для збору типу mime, якщо ви не можете легко отримати доступ до нього.
GONeale

4
Надання імені файлу Fileрезультату означає встановлення його FileDownloadNameвластивості, яка встановлює Content-Dispositionзаголовки для вас. І він правильно підтримує імена файлів utf-8, що не ContentDispositionдопомагає класу (див. Мій коментар тут для більш детальної інформації).
Фредерік

1
Так, дякую @ Frédéric, ти один із усіх постів ТА пояснив мені, що відбувається!
Нахт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.