Работа со статическими файлами в ASP.NET Core. Метод SendFileAsync

Современные web-приложения активно используют в своей работе разного рода статические файлы, например, файлы css, js, html и другие. Кроме этого, web-приложения могут как получать файлы от пользователей, так и наоборот — отправлять какие-либо данные в виде файлов пользователю. В ASP.NET Core имеются как стандартные компоненты middleware для работы со статическими файлами, так и отдельные методы, определенные в классе HttpResponse предназначенные для этих целей. Сегодня мы рассмотрим метод HttpResponse.SendFileAsync для работы со статическими файлами в ASP.NET Core.

Отправка файлов клиенту

Метод SendFileAsync() имеет ряд перегруженных версий. Для начала, воспользуемся наиболее простой из них, которая имеет следующий вид:

public static Task SendFileAsync(this HttpResponse response, string fileName, CancellationToken cancellationToken = default)

fileName — путь к отправляемому файлу. Может указываться как полный путь, так и относительны (относительно папки приложения).

Допустим, нам необходимо отправить пользователю файл «c:\temp\wow.jpeg». Напишем следующий исходный код приложения:

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        var app = builder.Build();

            app.Run(async context =>
            {
                await context.Response.SendFileAsync(@"c:\temp\wow.jpeg");
            });
        app.Run();
    }
}

Теперь запустим приложение и увидим:

ASP.NET Core по умолчанию пытается открыть файл в браузере, поэтому сразу после запуска мы видим отправленную сервером картинку. Что касается указания относительного пути к файлу, то продемонстрируем это следующим образом:

во-первых, создадим в корне проекта папкуwwwroot (если она у вас ещё не создана) и в этой папке — ещё одну папку с именем img:

В папку wwwroot/img поместим наш файл с картинкой, выберем его в обозревателе решений и установим для свойства «Копировать в выходной каталог» значение «Всегда копировать»:

Таким образом, наш файл будет каждый раз при сборке приложения копироваться в указанную папку. Теперь мы можем использовать в методе SendFileAsync путь относительно корня приложения:

app.Run(async context =>
{
    await context.Response.SendFileAsync(@"wwwroot\img\wow.jpeg");
});

Результат работы приложения будет такой же, как и в предыдущем примере. Тот факт, что ASP.NET Core по умолчанию пытается открыть файл в браузере, позволяет нам без лишних движений открывать в браузере html-страницы. Например, создадим в корне проекта два html-файла:

первый файл

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Главная</title>
</head>
<body>
    <h2>Главная страница приложения</h2>
</body>
</html>

второй файл:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h2>Data Page</h2>
</body>
</html>

В обозревателе решений Visual Studio должна получиться следующая структура

Теперь мы уже знаем как создавать конвейер обработки запросов в ASP.NET и можем написать следующий пример загрузки html-страниц:

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        var app = builder.Build();


       app.Run(async context =>
       {
          context.Response.ContentType = "text/html; charset=utf-8";
           if (context.Request.Path == "/")
               await context.Response.SendFileAsync("index.html");
           else if (context.Request.Path == "/data")
               await context.Response.SendFileAsync("data.html");
           else
           {
               context.Response.StatusCode = 404;
               await context.Response.WriteAsync("<h2>Not Found</h2>");
           }
       });


        app.Run();
    }
}

Здесь в middleware сопоставляется путь запроса с файлом, который необходимо отправить клиенту. Так, сразу после запуска приложения отправляется файл index.html, если путь /data, то отправляется файл data.html, а при любом другом пути запроса — возвращается код статуса 404 и текст Not Found. Также стоит обратить внимание на заголовок, который мы отправляем:

context.Response.ContentType = "text/html; charset=utf-8";

мы указываем, что отправляем текст в формате html. Если этого не сделать, то в браузере вместо странички мы увидим её исходный код. Таким образом, наше приложение будет работать как показано на рисунках ниже:

главная страница

/data

ошибка

Скачивание файла клиентом

Открытие файла в браузере по умолчанию полезно, когда мы хотим отправить клиенту готовую html-страницу, но становится неудобным, когда мы хотим, чтобы пользователь именно загружал файл себе на компьютер, например, ту же картинку wow.jpeg. Чтобы клиент начал загружать файл, нам необходимо задать значение HTTP-заголовка Content-Disposition следующим образом:

app.Run(async context =>
{
    context.Response.Headers.ContentDisposition = "attachment; filename=\"filename.jpeg\"";
    await context.Response.SendFileAsync(@"wwwroot\img\wow.jpeg");
});

здесь в заголовке мы указываем имя с которым будет загружаться файл, то есть наш файл wow.jpeg при запуске приложения будет загружен следующим образом:

Использование IFileInfo в методе SendFileAsync

Также, метод SendFileAsync() в качестве параметра может принимать не строку с именем файла, а объект, реализующий интерфейс IFileInfo.

app.Run(async context =>
{
    
    var provider = app.Environment.WebRootFileProvider;
    var file = provider.GetFileInfo(@"img\wow.jpeg");

    if (file.Exists)
    {
        context.Response.Headers.ContentDisposition = "attachment; filename=\"filename.jpeg\"";
        await context.Response.SendFileAsync(file);
    }
    else
    {
        context.Response.ContentType = "text/html; charset=utf-8";
        await context.Response.WriteAsync("<h2>Not Found</h2>");
    }
});

Здесь мы получили объект, реализующий интерфейс IFileProvider, который уже настроен на работу с папкой wwwroot нашего приложения (об этом свойстве рассказывалось здесь). Далее мы, используя метод GetFileInfo() получили информацию о файле и проверили его существование:

if (file.Exists)

если файл был найден, то от загружается с именем filename.jpeg на компьютер. Результат работы приложения будет такой же, как и в предыдущем примере.

Итого

Сегодня мы научились работать со статическими файлами в ASP.NET Core используя метод SendFileAsync объекта HttpResponse. По умолчанию. отправляемые файлы открываются в браузере, что удобно в случае, если нам необходимо отправить уже готовый html-файл пользователю. При необходимости, мы можем определить заголовок Content-Disposition и указать, что файл должен не открываться в браузере, а загружаться на компьютер пользователя как вложение.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии