Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
Для отправки клиенту файлов предназначен абстрактный класс FileResult, функционал которого реализуется в классах-наследниках:
FileContentResult: отправляет клиенту массив байтов, считанный из файла
VirtualFileResult: представляет простую отправку файла напрямую с сервера по виртуальному пути
FileStreamResult: создает поток - объект System.IO.Stream, с помощью которого считывает и отправляет файл клиенту
PhysicalFileResult: также отправляет файл с сервера, но для отправки используется реальный физический путь
Во первых трех случаях для отправки файлов применяется метод File(), а для создания объекта PhysicalFileResult используется метод PhysicalFile(). Только в зависимости от выбранного способа используется соответствующая перегруженная версия этого метода.
Для примера добавим в корень проекта папку Files, в которой находится файл book.pdf. И также добавим в папку wwwroot папку Files, в которой находится файл hello.txt:
Воспользуемся PhysicalFileResult
для отправки файла book.pdf клиенту:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Hosting; // для IWebHostEnvironment using System.IO; // для Path.Combine namespace HelloMvcApp.Controllers { public class HomeController : Controller { private readonly IWebHostEnvironment _appEnvironment; public HomeController(IWebHostEnvironment appEnvironment) { _appEnvironment = appEnvironment; } public IActionResult GetFile() { // Путь к файлу string file_path = Path.Combine(_appEnvironment.ContentRootPath, "Files/book.pdf"); // Тип файла - content-type string file_type = "application/pdf"; // Имя файла - необязательно string file_name = "book.pdf"; return PhysicalFile(file_path, file_type, file_name); } } }
Чтобы получить полный физический путь каталога относительно проекта, воспользуемся сервисом IWebHostEnvironment. Он автоматически передается в контроллер, и через конструктор контроллера мы его можем получить. Свойство ContentRootPath данного сервиса указывает на физический путь к каталогу проекта.
И, при обращении, например, по пути Home/GetFile нам будет предложено сохранить данный файл на локальном компьютере.
Похожим образом работает и класс FileContentResult, только используется метод File(), а вместо имени файла передается массив байтов, в который был считан файл:
// Отправка массива байтов public FileResult GetBytes() { string path = Path.Combine(_appEnvironment.ContentRootPath, "Files/book.pdf"); byte[] mas = System.IO.File.ReadAllBytes(path); string file_type = "application/pdf"; string file_name = "book2.pdf"; return File(mas, file_type, file_name); }
Если мы хотим возвратить объект FileStreamResult, то в качестве первого аргумента в методе File идет объект Stream для отправляемого файла:
// Отправка потока public FileResult GetStream() { string path = Path.Combine(_appEnvironment.ContentRootPath, "Files/book.pdf"); FileStream fs = new FileStream(path, FileMode.Open); string file_type = "application/pdf"; string file_name = "book3.pdf"; return File(fs, file_type, file_name); }
VirtualFileResult работает похожим образом, только возвращает файл по виртуальному пути. Здесь надо учитывать, что по умолчанию все пути к файлам в данном случае будут сопоставляться с папкой wwwroot. То есть нам надо помещать папки с файлами или отдельные файлы в каталог wwwroot:
public VirtualFileResult GetVirtualFile() { var filepath = Path.Combine("~/Files", "hello.txt"); return File(filepath, "text/plain", "hello.txt"); }
В данном случае предполагается, что файл "hello.txt" располагается в папке "wwwroot/Files/".
Во всех выше перечисленных случаях использование имени файла в качестве третьего параметра метода File/PhysicalFile необязательно. А вот тип файла обязательно надо передавать. Но подобное поведение может быть не всегда удобным: мы можем точно не знать тип отправляемых файлов, или файлы представляют самые разные типы. И в этом случае мы можем использовать универсальный тип application/octet-stream.