Работа со статическими файлами

Rick Anderson

Статические файлы, как HTML, CSS, изображения и JavaScript, являются активами, которые ASP.NET Core приложение может передавать клиентам напрямую.

Просмотрите или скачайте код

Передача статических файлов

Статические файлы обычно расположены в папке web root (<content-root>/wwwroot). См. о Content root и Web root в Введение в ASP.NET Core. Обычно корневая директория контента - это текущая директория, так что web root можно найти во время разработки.

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

Статические файлы можно хранить в любой подпапке web root и получить к ним доступ по относительному пути к корневой директории. Например, когда вы создаете проект веб приложения по умолчанию с помощью Visual Studio, внутри wwwroot есть несколько папок - css, images и js. URI для доступа к подпапке images:

  • http://<app>/images/<imageFileName>
  • http://localhost:9189/images/banner3.svg

Для передачи статических файлов вы должны настроить Связующее ПО (Middleware), чтобы добавить статические файлы в поток. Связующее ПО статических файлов можно настроить, если добавить в проект зависимость для пакета Microsoft.AspNetCore.StaticFiles, а затем вызвать из Startup.Configure метод расширения :dn:method:`~Microsoft.AspNetCore.Builder.StaticFileExtensions.UseStaticFiles`:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseStaticFiles();
}

app.UseStaticFiles(); делает файлы в web root (wwwroot по умолчанию) готовыми к передаче. Позже я покажу вам, как сделать другой контекст директории готовым к передаче с помощью UseStaticFiles.

“Microsoft.AspNetCore.StaticFiles” нужно включить в файл project.json.

Примечание

web root по умолчанию настроен на директорию wwwroot, но вы можете это изменить с помощью метода :dn:method:`~Microsoft.AspNetCore.Hosting.HostingAbstractionsWebHostBuilderExtensions.UseWebRoot`. См. Введение в ASP.NET Core.

Допустим, архитектура вашего проекта такова, что статические файлы находятся вне web root. Например:

  • wwwroot
    • css
    • images
    • ...
  • MyStaticFiles
    • test.png

Для доступа к test.png настройте связующее ПО статических файлов следующим образом:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseStaticFiles();

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles")
    });
}

Запрос по http://<app>/StaticFiles/test.png будет работать с файлом test.png.

Авторизация статических файлов

Модуль статических файлов не требует проверки авторизации. Любые файлы, с которыми он работает, включая те, что находятся в wwwroot, общедоступны. Если вы не хотите, чтобы файлы были общедоступны:

  • храните из за пределами wwwroot и любой директории, к оторой имеет доступ связующее ПО статических файлов и
  • работайте с ними через действие контроллера, возвращая :dn:class:`~Microsoft.AspNetCore.Mvc.FileResult`, где применяется авторизация

Просмотр директорий

Просмотр директорий позволяет пользователю вашего веб приложения просмотреть список директорий и файлов внутри конкретной директории. По умолчанию по причинам безопасности просмотр директорий отключен. Чтобы его включить, вызовите метод расширения :dn:method:`~Microsoft.AspNetCore.Builder.DirectoryBrowserExtensions.UseDirectoryBrowser` из Startup.Configure:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
        RequestPath = new PathString("/MyImages")
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
        RequestPath = new PathString("/MyImages")
    });
}

Добавьте требуемый сервис, вызвав метод расширения :dn:method:`~Microsoft.Extensions.DependencyInjection.DirectoryBrowserServiceExtensions.AddDirectoryBrowser` из Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDirectoryBrowser();
}

Код сверху разрешает просмотр директории для папки wwwroot/images с помощью URL http://<app>/MyImages со ссылками на каждый файл и папку:

../_images/dir-browse.png

См. Соображения_ по рискам для безопасности при включении просмотра директорий.

Обратите внимание на два вызова app.UseStaticFiles. Первый требуется для передачи CSS, изображений и JavaScript в wwwroot, а второй вызов - для просмотра директорий для папки wwwroot/images с помощью URL http://<app>/MyImages:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
        RequestPath = new PathString("/MyImages")
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
        RequestPath = new PathString("/MyImages")
    });
}

Передача документа по умолчанию

Домашняя страница по умолчанию - это обычно то место, откуда посетители начинают просматривать ваш сайт. Если вы хотите, чтобы пользователь мог увидеть домашнюю страницу, не вводя полный URI, вызовите метод расширения UseDefaultFiles из Startup.Configure:

public void Configure(IApplicationBuilder app)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

Примечание

При передаче файла по умолчанию :dn:method:`~Microsoft.AspNetCore.Builder.DefaultFilesExtensions.UseDefaultFiles` нужно вызывать перед UseStaticFiles. UseDefaultFiles переписывает URL, а не передает файл. Чтобы передать файл, вы должны включить связующее ПО статических файлов (UseStaticFiles).

С :dn:method:`~Microsoft.AspNetCore.Builder.DefaultFilesExtensions.UseDefaultFiles` запросы к папке будут искать:

  • default.htm
  • default.html
  • index.htm
  • index.html

Передаваться будет первый найденный файл из списка, как если бы запросом был полный URI.

В следующем коде показано, как изменить имя файла по умолчанию на mydefault.html.

public void Configure(IApplicationBuilder app)
{
    // Serve my app-specific default file, if present.
    DefaultFilesOptions options = new DefaultFilesOptions();
    options.DefaultFileNames.Clear();
    options.DefaultFileNames.Add("mydefault.html");
    app.UseDefaultFiles(options);
    app.UseStaticFiles();
}

UseFileServer

:dn:method:`~Microsoft.AspNetCore.Builder.FileServerExtensions.UseFileServer` совмещает функционал :dn:method:`~Microsoft.AspNetCore.Builder.StaticFileExtensions.UseStaticFiles`, :dn:method:`~Microsoft.AspNetCore.Builder.DefaultFilesExtensions.UseDefaultFiles` и :dn:method:`~Microsoft.AspNetCore.Builder.DirectoryBrowserExtensions.UseDirectoryBrowser`.

Следующий код разрешает передачу статических файлов и файла по умолчанию, но запрещает просмотр директорий:

app.UseFileServer();

Следующий код разрешает передачу статических файлов, файла по умолчанию и просмотр директорий:

app.UseFileServer(enableDirectoryBrowsing: true);

Как и с UseStaticFiles, UseDefaultFiles и UseDirectoryBrowser, если вы хотите передать файлы, которые существуют вне web root, вы создаете экземпляр и настраиваете объект :dn:class:`~Microsoft.AspNetCore.Builder.FileServerOptions`, который вы передаете в качестве параметра UseFileServer. Допустим, иерархия вашего приложения такова:

  • wwwroot
    • css
    • images
    • ...
  • MyStaticFiles
    • test.png
    • default.html

Далле, допустим, вы хотите включить для директории MyStaticFiles статические файлы, файл по умолчанию и просмотр. Это делается с помощью одного вызова :dn:class:`~Microsoft.AspNetCore.Builder.FileServerOptions`.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseStaticFiles();

    app.UseFileServer(new FileServerOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
        EnableDirectoryBrowsing = true
    });
}

Если enableDirectoryBrowsing установлен на true вам необходимо вызвать метод расширения :dn:method:`~Microsoft.Extensions.DependencyInjection.DirectoryBrowserServiceExtensions.AddDirectoryBrowser` из Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDirectoryBrowser();
}

Если использовать вышеуказанный код для данной иерархии:

URI Ответ
http://<app>/StaticFiles/test.png MyStaticFiles/test.png
http://<app>/StaticFiles MyStaticFiles/default.html

Если в директории MyStaticFiles нет именованных файлов по умолчанию, http://<app>/StaticFiles возвращает из директории список с рабочими ссылками:

../_images/db2.PNG

Примечание

UseDefaultFiles и UseDirectoryBrowser принимают url http://<app>/StaticFiles без слэша сзади и перенаправляют клиента на http://<app>/StaticFiles/ (со слэшем). Без слэша относительные URL внутри документа будут некорректными.

FileExtensionContentTypeProvider

Класс :dn:class:`~Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider` содержит коллекцию, которая приводит расширения файлов к контекстным типам MIME. В следующем примере несколько расширений файлов регистрируются как известные MIME типы, ”.rtf” заменен, а ”.mp4” удален.

public void Configure(IApplicationBuilder app)
{
    // Set up custom content types -associating file extension to MIME type
    var provider = new FileExtensionContentTypeProvider();
    // Add new mappings
    provider.Mappings[".myapp"] = "application/x-msdownload";
    provider.Mappings[".htm3"] = "text/html";
    provider.Mappings[".image"] = "image/png";
    // Replace an existing mapping
    provider.Mappings[".rtf"] = "application/x-msdownload";
    // Remove MP4 videos.
    provider.Mappings.Remove(".mp4");

    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
        RequestPath = new PathString("/MyImages"),
        ContentTypeProvider = provider
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot\images")),
        RequestPath = new PathString("/MyImages")
    });
}

См. Контекстные типы MIME.

Нестандартные контекстные типы

Связующее ПО статических файлов ASP.NET понимает почти 400 известных контекстных типов. Если пользователь запросит файл неизвестного типа, связующее ПО вернет ответ HTTP 404 (Not found). Если включен просмотр директорий, будет отображена ссылка к файлу, но URI вернет ошибку HTTP 404.

В следующем коде включена передача неизвестных типов, а неизвестный файл будет представлен как изображение.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseStaticFiles(new StaticFileOptions
    {
        ServeUnknownFileTypes = true,
        DefaultContentType = "image/png"
    });
}

В данном случае, если будет запрошен файл неизвестного типа, вернется изображение.

Предупреждение

Включение :dn:property:`~Microsoft.AspNetCore.Builder.StaticFileOptions.ServeUnknownFileTypes` является риском для безопасности. :dn:class:`~Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider` предлагает более безопасную альтернативу для передачи файлов с нестандартными расширениями.

Размышления

Предупреждение

UseDirectoryBrowser и UseStaticFiles могут привести к утечке данных. Мы рекомендуем не включать просмотр директорий в производственной версии приложения. С осторожностью используйте UseStaticFiles или UseDirectoryBrowser, поскольку доступными будут вся директория и поддиректории. Мы рекомендуем хранить открытый контент в своей директорий, как то <content root>/wwwroot, подальше от представлений, конфигурационных файлов и так далее.

  • ASP.NET Core приложения с хостингом на IIS используют ASP.NET Core Module, чтобы передавать все запросы приложению, включая запросы для статических файлов. Обработчик статических файлов IIS не используется, потому что у него нет шансов обработать запросы до того, как их обработает ASP.NET Core Module.

  • Чтобы удалить обработчик статических файлов IIS (на уровне сервера или веб сайта):

    • Перейдите к Modules
    • Выберите в списке StaticFileModule
    • В Actions нажмите Remove

Предупреждение

Если обработчик статических фалов IIS включен и ASP.NET Core Module (ANCM) настроен не корректно (например, если web.config не развернут), статические файлы будут переданы.

  • Файлы с кодом (включая c# и Razor) нужно размещать вне web root (wwwroot по умолчанию). Это разделяет контекст клиентской стороны и исходный код со стороны сервера, что помогает уберечь код со стороны сервера от утечки.
Поделись хорошей новостью с друзьями!
Следи за новостями!