Отправка файлов

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 18.11.2019

Для отправки клиенту файлов предназначен абстрактный класс FileResult, функционал которого реализуется в классах-наследниках:

  • FileContentResult: отправляет клиенту массив байтов, считанный из файла

  • VirtualFileResult: представляет простую отправку файла напрямую с сервера по виртуальному пути

  • FileStreamResult: создает поток - объект System.IO.Stream, с помощью которого считывает и отправляет файл клиенту

  • PhysicalFileResult: также отправляет файл с сервера, но для отправки используется реальный физический путь

Во первых трех случаях для отправки файлов применяется метод File(), а для создания объекта PhysicalFileResult используется метод PhysicalFile(). Только в зависимости от выбранного способа используется соответствующая перегруженная версия этого метода.

Для примера добавим в корень проекта папку Files, в которой находится файл book.pdf. И также добавим в папку wwwroot папку Files, в которой находится файл hello.txt:

Отправка файла по физическому пути в ASP.NET Core MVC 6

Загрузка файла по пути. PhysicalFileResult

Воспользуемся 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

Если мы хотим возвратить объект 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

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.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850