Содержание
В предыдущей части мы научились отправлять файлы клиенту и скачивать файлы на компьютер пользователя. Сегодня рассмотрим обратную операцию — загрузку файлов на сервер. Загрузка файлов на сервер в ASP.NET Core немногим сложнее, так как все же для этой операции нам придётся немного вспомнить работу с формами в HTML и научиться отправлять запросы POST на сервер.
IForm File
Все загружаемые на сервер файлы в ASP.NET Core представлены типом IFormFile
с помощью которого мы можем получить некоторые сведения о файле, а также получить поток для работы с данными файла. У IFormFile
определены следующие свойства:
Content |
Возвращает необработанный заголовок Content-Disposition отправленного файла. |
Content |
Возвращает необработанный заголовок Content-Type отправленного файла. |
File |
Возвращает имя файла из заголовка Content-Disposition. |
Headers |
Возвращает словарь заголовков отправленного файла. |
Length |
Возвращает длину файла в байтах. |
Name |
Возвращает имя поля формы из заголовка Content-Disposition. |
Как можно увидеть из представленной таблицы, три свойства IFormFile
из шести основаны на значениях заголовка Content-Disposition
, с которым мы уже знакомы по опыту отправки файлов пользователю. Также у IFormFile
определены три метода:
Copy |
Копирует содержимое отправленного файла в поток, указанный в параметрах метода. |
Copy |
Асинхронно копирует содержимое отправленного файла в поток, указанный в параметрах метода. |
Open |
Открывает поток запроса для чтения отправленного файла. |
Теперь попробуем использовать эти свойства и методы для загрузки файлов на сервер 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 для работы со статическими файлами о котором мы поговорим далее.