Одной из распространенных задач веб-приложений является отправка пользователю файлов. Для отправки файлов в ASP.NET Core применяется метод SendFileAsync(), который получает либо путь к файлу в виде строки, либо информацию о файле в виде объекта IFileInfo. Например, допустим нам надо отправить файл по адресу "D:\\forest.jpg":
Imports Microsoft.AspNetCore.Builder Imports Microsoft.AspNetCore.Http Module Program Sub Main(args As String()) Dim builder = WebApplication.CreateBuilder(args) Dim app = builder.Build() app.Run(Async Function(context As HttpContext) As Task Await context.Response.SendFileAsync("D:\\forest.jpg") End Function) app.Run() End Sub End Module
По умолчанию браузер попытается открыть файл. Так, в случае с изображениями они отображаются в браузере:
Также мы можем использовать относительные пути. Например, добавим в проект какой-нибудь файл (в моем случае это файл forest.jpg):
Для этого файла в окне свойств установим для опции Copy to Output Directory значение Copy if newer
или Copy always
, чтобы файл автоматически копировался в выходной каталог при построении приложения. И установим относительный путь относительно корня приложения:
Imports Microsoft.AspNetCore.Builder Imports Microsoft.AspNetCore.Http Module Program Sub Main(args As String()) Dim builder = WebApplication.CreateBuilder(args) Dim app = builder.Build() app.Run(Async Function(context As HttpContext) As Task Await context.Response.SendFileAsync("forest.jpg") End Function) app.Run() End Sub End Module
Подобным образом мы можно отправлять и другие типы файлов, например, html-страницу. Так, определим в проекте новую папку, которую назовем html. В эту папку добавим новый файл index.html:
Определим в файле index.html следующий код:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>METANIT.COM</title> </head> <body> <h2>Hello ASP.NET Core!</h2> </body> </html>
Определим для отправки веб-страницы следующий код:
Imports Microsoft.AspNetCore.Builder Imports Microsoft.AspNetCore.Http Module Program Sub Main(args As String()) Dim builder = WebApplication.CreateBuilder(args) Dim app = builder.Build() app.Run(Async Function(context As HttpContext) As Task context.Response.ContentType = "text/html; charset=utf-8" Await context.Response.SendFileAsync("html/index.html") End Function) app.Run() End Sub End Module
В итоге при обращении к приложению сервер возвратит страницу index.html:
Теперь немного усложним задачу. Добавим в проект в папку html еще пару файлов. Назовем их, к примеру, about.html и contact.html.
Для отправки этих файлов определим следующий код:
Imports Microsoft.AspNetCore.Builder Imports Microsoft.AspNetCore.Http Module Program Sub Main(args As String()) Dim builder = WebApplication.CreateBuilder(args) Dim app = builder.Build() app.Run(Async Function(context As HttpContext) As Task Dim path = context.Request.Path.Value Dim fullPath = $"html/{path}" Dim response = context.Response response.ContentType = "text/html; charset=utf-8" If IO.File.Exists(fullPath) Then Await response.SendFileAsync(fullPath) Else response.StatusCode = 404 Await response.WriteAsync("<h2>Not Found</h2>") End If End Function) app.Run() End Sub End Module
Когда приходит запрос, мы сопоставляем путь запроса (path) с файлами в папке html. То есть если переменная path равна "about.html", то нам надо оправить в ответ
файл about.html
. При этом проверяем наличие файла. Если он есть в папке, то отправляем данный файл. Если нет, то отправляем статусный код 404 и сообщение, что ресус не найден:
Стоит отметить, что в ASP.NET Core уже имеется встороенный middleware, который позволяет упростить работу со статическими файлами.
По умолчанию браузер пытается открыть отправляемый файл, что может быть полезно в случае файлов html - мы можем определить файл html и таким образом отправить клиенту веб-страницу. Но также может быть необходимо, чтобы браузер загружал файл без его открытия. В этом случае мы можем установить для заголовка "Content-Disposition" значение "attachment":
Imports Microsoft.AspNetCore.Builder Imports Microsoft.AspNetCore.Http Module Program Sub Main(args As String()) Dim builder = WebApplication.CreateBuilder(args) Dim app = builder.Build() app.Run(Async Function(context As HttpContext) As Task context.Response.Headers.ContentDisposition = "attachment; filename=my_forest.jpg" Await context.Response.SendFileAsync("forest.jpg") End Function) app.Run() End Sub End Module
В этом случае загруженный файл получит имя "my_forest.jpg"
В примерах выше применялась версия метода SendFileAsync(), которая получает путь к файлу в виде строки. Также можно использовать другую версию, которая получает информацию о файле в виде объекта IFileInfo:
Imports Microsoft.AspNetCore.Builder Imports Microsoft.AspNetCore.Http Imports Microsoft.Extensions.FileProviders Module Program Sub Main(args As String()) Dim builder = WebApplication.CreateBuilder(args) Dim app = builder.Build() app.Run(Async Function(context As HttpContext) As Task Dim fileProvider = New PhysicalFileProvider(IO.Directory.GetCurrentDirectory()) Dim fileinfo = fileProvider.GetFileInfo("forest.jpg") context.Response.Headers.ContentDisposition = "attachment; filename=my_forest2.jpg" Await context.Response.SendFileAsync(fileinfo) End Function) app.Run() End Sub End Module
В этом случае сначала необходимо определить объект PhysicalFileProvider, конструктор которого получает каталог для поиска файлов. В
его метод fileProvider.GetFileInfo()
передается путь к файлу в рамках этого каталога. А результатом метода является объект IFileInfo, который передается
в SendFileAsync()