Работа со статическими файлами в ASP.NET Core. Загрузка файлов на сервер

В предыдущей части мы научились отправлять файлы клиенту и скачивать файлы на компьютер пользователя. Сегодня рассмотрим обратную операцию — загрузку файлов на сервер. Загрузка файлов на сервер в ASP.NET Core немногим сложнее, так как все же для этой операции нам придётся немного вспомнить работу с формами в HTML и научиться отправлять запросы POST на сервер.

IFormFile

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

ContentDisposition Возвращает необработанный заголовок Content-Disposition отправленного файла.
ContentType Возвращает необработанный заголовок Content-Type отправленного файла.
FileName Возвращает имя файла из заголовка Content-Disposition.
Headers Возвращает словарь заголовков отправленного файла.
Length Возвращает длину файла в байтах.
Name Возвращает имя поля формы из заголовка Content-Disposition.

 

Как можно увидеть из представленной таблицы, три свойства IFormFile из шести основаны на значениях заголовка Content-Disposition, с которым мы уже знакомы по опыту отправки файлов пользователю. Также у IFormFile определены три метода:

CopyTo Копирует содержимое отправленного файла в поток, указанный в параметрах метода.
CopyToAsync Асинхронно копирует содержимое отправленного файла в поток, указанный в параметрах метода.
OpenReadStream Открывает поток запроса для чтения отправленного файла.

 

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

HTML-форма для загрузки файлов на сервер

Создадим пустой проект ASP.NET Core и добавим в него две папки: wwwroot и html следующим образом:

Теперь добавим в папку html файл index.html. Чтобы не писать вручную основной html-код страницы в блокноте, можно добавить этот файл, используя Visual Studio:

В проект будет добавлен html-файл со следующим содержанием:

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

</body>
</html>

Теперь добавим в этот файл html-форму:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Загрузка файла на сервер ASP.NET Core</title>
</head>
<body>
    <p>Выберите файл для загрузки</p>
    <form method="post" enctype="multipart/form-data">
        <input type="file" name="uploads" /><br>
        <input type="submit" value="Загрузить" />
    </form>
</body>
</html>

В этой форме мы определили одно поле input с типом file для указания загружаемого файла, кнопку «Загрузить» клик по которой будет выполнять запрос POST на сервер. Также, чтобы вместе с формой отправлялись данные файла мы указали у формы тип данных «multipart/form-data». В запущенном приложении эта форма будет выглядеть следующим образом:

Теперь напишем небольшой компонент middleware который будет принимать и обрабатывать запросы от пользователя.

Middleware для загрузки файла на сервер

Наше приложение должно обрабатывать два типа запросов: GET — для отправки пользователю формы для загрузки файла и POST — для получения файла от пользователя. Мы уже вкратце изучали обработку запроса пользователя, поэтому не будем повторяться и сразу напишем следующий middleware (ниже представлен весь исходный код приложения):

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

             HttpRequest request = context.Request;

             if (request.Method == "POST")
             {
                 //создаем папку uploads для загружаемых файлов
                 var path = Path.Combine(app.Environment.ContentRootPath, "uploads");
                 Directory.CreateDirectory(path);

                 //получаем коллекцию загружаемых файлов
                 IFormFileCollection files = request.Form.Files;
                 foreach (IFormFile file in files)
                 {
                     string fileFullPath = Path.Combine(path, file.FileName);
                     // сохраняем файл в папку uploads
                     using (var fileStream = new FileStream(fileFullPath, FileMode.Create))
                     {
                         await file.CopyToAsync(fileStream);
                     }
                 }
                 await context.Response.WriteAsync("<b>Файлы загружены</b>");
             }
             else
             {
                 await context.Response.SendFileAsync(@"wwwroot\html\index.html");
             }
         });

         app.Run();
     }
 }

Middleware действует следующим образом: во-первых, проверяется метод запроса:

if (request.Method == "POST")

если метод POST, то считаем, что пользователь загружает файл на сервер, если же нет, то мы отправляем пользователю наш файл index.html с формой:

await context.Response.SendFileAsync(@"wwwroot\html\index.html");

Во-вторых, при обработке запроса POST мы создаем директорию в которой будем сохранять файлы:

var path = Path.Combine(app.Environment.ContentRootPath, "uploads");
Directory.CreateDirectory(path);

файлы сохраняются в папку uploads, которая будет находится в корневой папке проекта. Далее, мы получаем коллекцию файлов формы

IFormFileCollection files = request.Form.Files;

Несмотря на то, что мы предусмотрели загрузку всего одного файла на сервер, тем не менее, код формы может измениться и, например, в форме будут отправляться не один, а 10 файлов, поэтому в middleware предусмотрен цикл foreach в котором перебираются все элементы коллекции (объекты, реализующие IFormFile) и каждый файл сохраняется на диск:

foreach (IFormFile file in files)
{
    string fileFullPath = Path.Combine(path, file.FileName);
    // сохраняем файл в папку uploads
    using (var fileStream = new FileStream(fileFullPath, FileMode.Create))
    {
        await file.CopyToAsync(fileStream);
    }
}

После того как файлы сохранены, пользователю выводится сообщение об успешной загрузке:

await context.Response.WriteAsync("<b>Файлы загружены</b>");

Ниже представлены работа нашего приложения.

Вид приложения сразу после запуска:

Успешная загрузка файла

Вид обозревателя решений Visual Studio после загрузки файла на сервер:

Итого

Сегодня мы научились загружать файлы на сервер ASP.NET Core и немного подробнее изучили работу с запросами пользователя, в частности, использовали свойства Method и Form для обработки запроса. Загружаемые на сервер файлы представляются в виде коллекции IFormFileCollection в которой каждый элемент — это один файл, представленный типом IFormFile. Стоит также напомнить, что в ASP.NET Core имеется штатный middleware для работы со статическими файлами о котором мы поговорим далее.

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