Статические файлы в ASP.NET CoreStatic files in ASP.NET Core

Авторы: Рик Андерсон (Rick Anderson) и Скотт Адди (Scott Addie)By Rick Anderson and Scott Addie

Статические файлы, такие как HTML, CSS, изображения и JavaScript, являются ресурсами, которые приложения ASP.NET Core предоставляют клиентам напрямую.Static files, such as HTML, CSS, images, and JavaScript, are assets an ASP.NET Core app serves directly to clients. Для обслуживания таких файлов требуется настроить некоторые параметры.Some configuration is required to enable serving of these files.

Просмотреть или скачать образец кода (как скачивать)View or download sample code (how to download)

Обслуживание статических файловServe static files

Статические файлы хранятся в корневом веб-каталоге проекта.Static files are stored within the project's web root directory. Каталог по умолчанию — <корневой_каталог_содержимого>/wwwroot, но его можно изменить через метод UseWebRoot.The default directory is <content_root>/wwwroot, but it can be changed via the UseWebRoot method. Дополнительные сведения см. в разделах Корневой каталог содержимого и Корневой веб-каталог.See Content root and Web root for more information.

Веб-узел приложения должен знать о расположении корневого каталога содержимого.The app's web host must be made aware of the content root directory.

Метод WebHost.CreateDefaultBuilder устанавливает текущий каталог в качестве корневого каталога содержимого:The WebHost.CreateDefaultBuilder method sets the content root to the current directory:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

Установите текущий каталог в качестве корневого каталога содержимого, вызвав UseContentRoot в методе Program.Main:Set the content root to the current directory by invoking UseContentRoot inside of Program.Main:

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

        host.Run();
    }        
}

Статические файлы доступны по относительному пути от корневого веб-каталога.Static files are accessible via a path relative to the web root. Например, шаблон проекта Web Application содержит несколько папок в папке wwwroot:For example, the Web Application project template contains several folders within the wwwroot folder:

  • wwwrootwwwroot
    • csscss
    • imagesimages
    • jsjs

Формат URI для доступа к файлу во вложенной папке images следующий: http://<адрес_сервера>/images/<имя_файла_изображения> .The URI format to access a file in the images subfolder is http://<server_address>/images/<image_file_name>. Например, http://localhost:9189/images/banner3.svg .For example, http://localhost:9189/images/banner3.svg.

Если код предназначен для .NET Framework, добавьте в проект пакет Microsoft.AspNetCore.StaticFiles.If targeting .NET Framework, add the Microsoft.AspNetCore.StaticFiles package to the project. Если код предназначен для .NET Core, то этот пакет уже включен в метапакет Microsoft.AspNetCore.App.If targeting .NET Core, the Microsoft.AspNetCore.App metapackage includes this package.

Если код предназначен для .NET Framework, добавьте в проект пакет Microsoft.AspNetCore.StaticFiles.If targeting .NET Framework, add the Microsoft.AspNetCore.StaticFiles package to the project. Если код предназначен для .NET Core, то этот пакет уже включен в метапакет Microsoft.AspNetCore.All.If targeting .NET Core, the Microsoft.AspNetCore.All metapackage includes this package.

Добавьте пакет Microsoft.AspNetCore.StaticFiles в проект.Add the Microsoft.AspNetCore.StaticFiles package to the project.

Настройте ПО промежуточного слоя, позволяющее обслуживать статические файлы.Configure the middleware which enables the serving of static files.

Обслуживание файлов в корневом веб-каталогеServe files inside of web root

Вызовите метод UseStaticFiles в Startup.Configure:Invoke the UseStaticFiles method within Startup.Configure:

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

Эта перегрузка метода UseStaticFiles не принимает параметров, она помечает файлы в корневой веб-каталог как обслуживаемые.The parameterless UseStaticFiles method overload marks the files in web root as servable. Следующая разметка ссылается на wwwroot/images/banner1.svg:The following markup references wwwroot/images/banner1.svg:

<img src="~/images/banner1.svg" alt="ASP.NET" class="img-responsive" />

В приведенном выше коде знак тильды ~/ указывает на корневой веб-каталог.In the preceding code, the tilde character ~/ points to webroot. Дополнительные сведения см. в разделе Корневой веб-каталог.For more information, see Web root.

Обслуживание файлов вне корневого веб-каталогаServe files outside of web root

Пусть имеется иерархия каталогов, в которой статические файлы обслуживаются вне корневого веб-каталога:Consider a directory hierarchy in which the static files to be served reside outside of the web root:

  • wwwrootwwwroot
    • csscss
    • imagesimages
    • jsjs
  • MyStaticFilesMyStaticFiles
    • imagesimages
      • banner1.svgbanner1.svg

В запросе можно получить доступ к файлу banner1.svg, настроив ПО промежуточного слоя для статических файлов следующим образом:A request can access the banner1.svg file by configuring the Static File Middleware as follows:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

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

В приведенном выше коде доступ к иерархии каталога MyStaticFiles представляется через сегмент URI StaticFiles.In the preceding code, the MyStaticFiles directory hierarchy is exposed publicly via the StaticFiles URI segment. Запрос http://<адрес_сервера> /StaticFiles/images/banner1.svg обслуживает файлы banner1.svg.A request to http://<server_address>/StaticFiles/images/banner1.svg serves the banner1.svg file.

Следующая разметка ссылается на MyStaticFiles/images/banner1.svg:The following markup references MyStaticFiles/images/banner1.svg:

<img src="~/StaticFiles/images/banner1.svg" alt="ASP.NET" class="img-responsive" />

Установка заголовков HTTP-ответовSet HTTP response headers

Для установки заголовков HTTP-ответов можно использовать объект StaticFileOptions.A StaticFileOptions object can be used to set HTTP response headers. Кроме настройки обслуживания статических файлов в корне веб-каталога, следующий код также устанавливает заголовок Cache-Control:In addition to configuring static file serving from the web root, the following code sets the Cache-Control header:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    var cachePeriod = env.IsDevelopment() ? "600" : "604800";
    app.UseStaticFiles(new StaticFileOptions
    {
        OnPrepareResponse = ctx =>
        {
            // Requires the following import:
            // using Microsoft.AspNetCore.Http;
            ctx.Context.Response.Headers.Append("Cache-Control", $"public, max-age={cachePeriod}");
        }
    });
}

Метод HeaderDictionaryExtensions.Append содержится в пакете Microsoft.AspNetCore.Http.The HeaderDictionaryExtensions.Append method exists in the Microsoft.AspNetCore.Http package.

Файлы, к которым был предоставлен доступ, кэшируются в течение 10 минут (600 секунд) в среде разработки:The files have been made publicly cacheable for 10 minutes (600 seconds) in the Development environment:

Добавлены заголовки ответов, включая заголовок Cache-Control

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

ПО промежуточного слоя для статических файлов не предоставляет возможности авторизации.The Static File Middleware doesn't provide authorization checks. Все обслуживаемые им файлы, включая расположенные в wwwroot, находятся в открытом доступе.Any files served by it, including those under wwwroot, are publicly accessible. Для обслуживания файлов с авторизацией:To serve files based on authorization:

  • Сохраните файлы в любом каталоге за пределами каталога wwwroot, к которому имеет доступ ПО промежуточного слоя для статических файлов.Store them outside of wwwroot and any directory accessible to the Static File Middleware.

  • Обслуживайте их через метод действия, к которому применима авторизация.Serve them via an action method to which authorization is applied. Возвращайте объект FileResult:Return a FileResult object:

    [Authorize]
    public IActionResult BannerImage()
    {
        var file = Path.Combine(Directory.GetCurrentDirectory(), 
                                "MyStaticFiles", "images", "banner1.svg");
    
        return PhysicalFile(file, "image/svg+xml");
    }
    

Просмотр каталоговEnable directory browsing

Просмотр каталогов позволяет пользователям веб-приложениям просматривать файлы и каталоги внутри определенного каталога.Directory browsing allows users of your web app to see a directory listing and files within a specified directory. По соображениям безопасности просмотр каталогов отключен по умолчанию (см. раздел Особенности).Directory browsing is disabled by default for security reasons (see Considerations). Разрешить просмотр каталогов можно вызвав метод UseDirectoryBrowser в Startup.Configure:Enable directory browsing by invoking the UseDirectoryBrowser method in Startup.Configure:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

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

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

Добавим необходимые службы путем вызова метода AddDirectoryBrowser из Startup.ConfigureServices:Add required services by invoking the AddDirectoryBrowser method from Startup.ConfigureServices:

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

Приведенный выше код разрешает просмотр папки wwwroot/images с помощью URL-адреса http://<адрес_сервера>/MyImages, со ссылками на все файлы и папки:The preceding code allows directory browsing of the wwwroot/images folder using the URL http://<server_address>/MyImages, with links to each file and folder:

просмотр каталогов

Информацию об угрозе безопасности при включении просмотра каталогов см. в разделе Особенности.See Considerations on the security risks when enabling browsing.

Обратите внимание на два вызова метода UseStaticFiles в следующем примере.Note the two UseStaticFiles calls in the following example. Первый вызов включает обслуживание статических файлов в папке wwwroot.The first call enables the serving of static files in the wwwroot folder. Второй вызов включает просмотр каталогов в папке wwwroot/images с помощью URL-адреса http://<адрес_сервера>/MyImages:The second call enables directory browsing of the wwwroot/images folder using the URL http://<server_address>/MyImages:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

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

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

Обслуживание документа по умолчаниюServe a default document

Домашняя страница по умолчанию является для посетителей логической отправной точкой при посещении веб-сайта.Setting a default home page provides visitors a logical starting point when visiting your site. Для обслуживания страницы по умолчанию без указания полного имени URI вызовите метод UseDefaultFiles из Startup.Configure:To serve a default page without the user fully qualifying the URI, call the UseDefaultFiles method from Startup.Configure:

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

Важно!

Для обслуживания файла по умолчанию метод UseDefaultFilesдолжен быть вызван до метода UseStaticFiles.UseDefaultFiles must be called before UseStaticFiles to serve the default file. Метод UseDefaultFiles фактически не обслуживает файл, а только перезаписывает URL-адрес.UseDefaultFiles is a URL rewriter that doesn't actually serve the file. Для обслуживания файла включите ПО промежуточного слоя для статических файлов, вызвав метод UseStaticFiles.Enable Static File Middleware via UseStaticFiles to serve the file.

При вызове метода UseDefaultFiles запросы к папке будут искать следующие файлы:With UseDefaultFiles, requests to a folder search for:

  • default.htmdefault.htm
  • default.htmldefault.html
  • index.htmindex.htm
  • index.htmlindex.html

Первый найденный файл из списка будет обслужен, как будто был введен полный URI.The first file found from the list is served as though the request were the fully qualified URI. URL-адрес в браузере будет соответствовать запрошенному URI.The browser URL continues to reflect the URI requested.

Следующий код позволяет изменить имя файла по умолчанию на mydefault.html:The following code changes the default file name to 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();
}

UseFileServerUseFileServer

Метод UseFileServer объединяет в себе функции UseStaticFiles, UseDefaultFiles и UseDirectoryBrowser.UseFileServer combines the functionality of UseStaticFiles, UseDefaultFiles, and UseDirectoryBrowser.

Следующий пример кода позволяет обслуживать статические файлы и файл по умолчанию.The following code enables the serving of static files and the default file. Просмотр каталогов отключен.Directory browsing isn't enabled.

app.UseFileServer();

Следующий код отличается от предыдущей перегрузки метода без параметров включением просмотра каталогов:The following code builds upon the parameterless overload by enabling directory browsing:

app.UseFileServer(enableDirectoryBrowsing: true);

Пусть имеется следующая иерархия каталогов:Consider the following directory hierarchy:

  • wwwrootwwwroot
    • csscss
    • imagesimages
    • jsjs
  • MyStaticFilesMyStaticFiles
    • imagesimages
      • banner1.svgbanner1.svg
    • default.htmldefault.html

Следующий пример кода включает обслуживание статических файлов, файлы по умолчанию и просмотр каталога MyStaticFiles:The following code enables static files, default files, and directory browsing of MyStaticFiles:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(); // For the wwwroot folder

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

Метод AddDirectoryBrowser должен вызываться при значении true свойства EnableDirectoryBrowsing:AddDirectoryBrowser must be called when the EnableDirectoryBrowsing property value is true:

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

При указанных выше коде и иерархии файлов URL-адреса будут разрешаться следующим образом:Using the file hierarchy and preceding code, URLs resolve as follows:

URIURI ОтветResponse
http://<адрес_сервера>/StaticFiles/images/banner1.svghttp://<server_address>/StaticFiles/images/banner1.svg MyStaticFiles/images/banner1.svgMyStaticFiles/images/banner1.svg
http://<адрес_сервера>/StaticFileshttp://<server_address>/StaticFiles MyStaticFiles/default.htmlMyStaticFiles/default.html

Если в каталоге MyStaticFiles отсутствует файл с именем по умолчанию, то http://<адрес_сервера>/StaticFiles возвращает список содержимого каталога с доступными для перехода ссылками:If no default-named file exists in the MyStaticFiles directory, http://<server_address>/StaticFiles returns the directory listing with clickable links:

Список статических файлов

Примечание

UseDefaultFiles и UseDirectoryBrowser выполняют перенаправление на стороне клиента из http://{SERVER ADDRESS}/StaticFiles (без косой черты в конце) в http://{SERVER ADDRESS}/StaticFiles/ (с косой чертой в конце).UseDefaultFiles and UseDirectoryBrowser perform a client-side redirect from http://{SERVER ADDRESS}/StaticFiles (without a trailing slash) to http://{SERVER ADDRESS}/StaticFiles/ (with a trailing slash). Относительные URL-адреса в каталоге StaticFiles считаются недопустимыми без косой черты в конце.Relative URLs within the StaticFiles directory are invalid without a trailing slash.

FileExtensionContentTypeProviderFileExtensionContentTypeProvider

Класс FileExtensionContentTypeProvider содержит свойство Mappings, которое служит для сопоставления расширений файлов и типов содержимого MIME.The FileExtensionContentTypeProvider class contains a Mappings property serving as a mapping of file extensions to MIME content types. В следующем примере несколько расширений файлов регистрируются в известные типы MIME.In the following sample, several file extensions are registered to known MIME types. Расширение .rtf заменяется, а .mp4 удаляется.The .rtf extension is replaced, and .mp4 is removed.

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 = "/MyImages",
        ContentTypeProvider = provider
    });

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

См. раздел Типы содержимого MIME.See MIME content types.

Нестандартные типы содержимогоNon-standard content types

ПО промежуточного слоя для статических файлов воспринимает почти 400 известных типов содержимого файлов.Static File Middleware understands almost 400 known file content types. Если пользователь запрашивает файл неизвестного типа, ПО промежуточного слоя статических файлов передает запрос следующему компоненту ПО промежуточного слоя в конвейере.If the user requests a file with an unknown file type, Static File Middleware passes the request to the next middleware in the pipeline. Если ПО промежуточного слоя не удается обработать запрос, возвращается ответ 404 Не найдено.If no middleware handles the request, a 404 Not Found response is returned. Если просмотр каталогов разрешен, то в списке каталогов отображается ссылка на файл.If directory browsing is enabled, a link to the file is displayed in a directory listing.

Следующий код включает обслуживание неизвестных типов и обслуживает неизвестные файлы как изображения:The following code enables serving unknown types and renders the unknown file as an image:

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

При выполнении вышеописанного кода ответ на запрос файла с неизвестным типом содержимого вернется в виде изображения.With the preceding code, a request for a file with an unknown content type is returned as an image.

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

Включение параметра ServeUnknownFileTypes представляет угрозу безопасности.Enabling ServeUnknownFileTypes is a security risk. По умолчанию он отключен, и его использование не рекомендуется.It's disabled by default, and its use is discouraged. Использование класса FileExtensionContentTypeProvider является более безопасной альтернативой для обслуживания файлов с нестандартными расширениями.FileExtensionContentTypeProvider provides a safer alternative to serving files with non-standard extensions.

ОсобенностиConsiderations

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

Использование UseDirectoryBrowser и UseStaticFiles может привести к утечке конфиденциальной информации.UseDirectoryBrowser and UseStaticFiles can leak secrets. Настоятельно рекомендуется отключать просмотр каталогов в рабочей среде.Disabling directory browsing in production is highly recommended. Тщательно проверьте, просмотр каких каталогов разрешен посредством UseStaticFiles или UseDirectoryBrowser.Carefully review which directories are enabled via UseStaticFiles or UseDirectoryBrowser. Весь каталог и его подкаталоги становятся общедоступными.The entire directory and its sub-directories become publicly accessible. Храните файлы, предназначенные для общего доступа, в выделенных каталогах, таких как <корневой_каталог_содержимого>/wwwroot.Store files suitable for serving to the public in a dedicated directory, such as <content_root>/wwwroot. Отделите эти файлы от представлений MVC, страниц Razor (только для версии 2.x), файлов конфигурации и т.д.Separate these files from MVC views, Razor Pages (2.x only), configuration files, etc.

  • К URL-адресам содержимого, к которому предоставлен доступ методами UseDirectoryBrowser и UseStaticFiles, применяются те же требования по регистрозависимости и запрещенным символам, что и к базовой файловой системе.The URLs for content exposed with UseDirectoryBrowser and UseStaticFiles are subject to the case sensitivity and character restrictions of the underlying file system. Например, в Windows не учитывается регистр, а в macOS и Linux — учитывается.For example, Windows is case insensitive—macOS and Linux aren't.

  • Приложения ASP.NET Core, размещенные в IIS, используют Модуль Core ASP.NET для перенаправления всех запросов к приложению, включая запросы статических файлов.ASP.NET Core apps hosted in IIS use the ASP.NET Core Module to forward all requests to the app, including static file requests. Обработчик статических файлов IIS не используется.The IIS static file handler isn't used. Не существует возможности обработать запросы до того, как их обработает модуль.It has no chance to handle requests before they're handled by the module.

  • Выполните следующие шаги в диспетчере служб IIS для удаления обработчика статических файлов IIS на уровне сервера или веб-сайта:Complete the following steps in IIS Manager to remove the IIS static file handler at the server or website level:

    1. Перейдите к компоненту Модули.Navigate to the Modules feature.
    2. Выберите в списке модуль StaticFileModule.Select StaticFileModule in the list.
    3. Нажмите кнопку Удалить в боковой панели Действия.Click Remove in the Actions sidebar.

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

Если обработчик статических файлов IIS включен и модуль ASP.NET Core настроен неправильно, то статические файлы будут обслуживаться.If the IIS static file handler is enabled and the ASP.NET Core Module is configured incorrectly, static files are served. Это может случиться, если, например, не был развернут файл web.config.This happens, for example, if the web.config file isn't deployed.

  • Размещайте файлы с кодом (включая .cs и .cshtml) за пределами корневого веб-каталога проекта приложения.Place code files (including .cs and .cshtml) outside of the app project's web root. Таким образом, в приложении создается логическое разделение между клиентским содержимым и серверным кодом.A logical separation is therefore created between the app's client-side content and server-based code. Это предотвращает утечку серверного кода.This prevents server-side code from being leaked.

Дополнительные ресурсыAdditional resources