252 lines
15 KiB
Markdown
252 lines
15 KiB
Markdown
---
|
|
title: Work with static files in ASP.NET Core
|
|
author: rick-anderson
|
|
description: Learn how to serve and secure static files and configure static file hosting middleware behaviors in an ASP.NET Core web app.
|
|
manager: wpickett
|
|
ms.author: riande
|
|
ms.custom: mvc
|
|
ms.date: 01/18/2018
|
|
ms.devlang: csharp
|
|
ms.prod: asp.net-core
|
|
ms.technology: aspnet
|
|
ms.topic: article
|
|
uid: fundamentals/static-files
|
|
---
|
|
# Work with static files in ASP.NET Core
|
|
|
|
By [Rick Anderson](https://twitter.com/RickAndMSFT) and [Scott Addie](https://twitter.com/Scott_Addie)
|
|
|
|
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 to serving of these files.
|
|
|
|
[View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/fundamentals/static-files/samples) ([how to download](xref:tutorials/index#how-to-download-a-sample))
|
|
|
|
## Serve static files
|
|
|
|
Static files are stored within your project's web root directory. The default directory is *\<content_root>/wwwroot*, but it can be changed via the [UseWebRoot](/dotnet/api/microsoft.aspnetcore.hosting.hostingabstractionswebhostbuilderextensions.usewebroot#Microsoft_AspNetCore_Hosting_HostingAbstractionsWebHostBuilderExtensions_UseWebRoot_Microsoft_AspNetCore_Hosting_IWebHostBuilder_System_String_) method. See [Content root](xref:fundamentals/index#content-root) and [Web root](xref:fundamentals/index#web-root) for more information.
|
|
|
|
The app's web host must be made aware of the content root directory.
|
|
|
|
# [ASP.NET Core 2.x](#tab/aspnetcore2x)
|
|
|
|
The `WebHost.CreateDefaultBuilder` method sets the content root to the current directory:
|
|
|
|
[!code-csharp[](../common/samples/WebApplication1DotNetCore2.0App/Program.cs?name=snippet_Main&highlight=9)]
|
|
|
|
# [ASP.NET Core 1.x](#tab/aspnetcore1x)
|
|
|
|
Set the content root to the current directory by invoking [UseContentRoot](/dotnet/api/microsoft.aspnetcore.hosting.hostingabstractionswebhostbuilderextensions.usecontentroot#Microsoft_AspNetCore_Hosting_HostingAbstractionsWebHostBuilderExtensions_UseContentRoot_Microsoft_AspNetCore_Hosting_IWebHostBuilder_System_String_) inside of `Program.Main`:
|
|
|
|
[!code-csharp[](static-files/samples/1x/Program.cs?name=snippet_ProgramClass&highlight=7)]
|
|
|
|
---
|
|
|
|
Static files are accessible via a path relative to the web root. For example, the **Web Application** project template contains several folders within the *wwwroot* folder:
|
|
|
|
* **wwwroot**
|
|
* **css**
|
|
* **images**
|
|
* **js**
|
|
|
|
The URI format to access a file in the *images* subfolder is *http://\<server_address>/images/\<image_file_name>*. For example, *http://localhost:9189/images/banner3.svg*.
|
|
|
|
# [ASP.NET Core 2.x](#tab/aspnetcore2x)
|
|
|
|
If targeting .NET Framework, add the [Microsoft.AspNetCore.StaticFiles](https://www.nuget.org/packages/Microsoft.AspNetCore.StaticFiles/) package to your project. If targeting .NET Core, the [Microsoft.AspNetCore.All metapackage](xref:fundamentals/metapackage) includes this package.
|
|
|
|
# [ASP.NET Core 1.x](#tab/aspnetcore1x)
|
|
|
|
Add the [Microsoft.AspNetCore.StaticFiles](https://www.nuget.org/packages/Microsoft.AspNetCore.StaticFiles/) package to your project.
|
|
|
|
---
|
|
|
|
Configure the [middleware](xref:fundamentals/middleware/index) which enables the serving of static files.
|
|
|
|
### Serve files inside of web root
|
|
|
|
Invoke the [UseStaticFiles](/dotnet/api/microsoft.aspnetcore.builder.staticfileextensions.usestaticfiles#Microsoft_AspNetCore_Builder_StaticFileExtensions_UseStaticFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_) method within `Startup.Configure`:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupStaticFiles.cs?name=snippet_ConfigureMethod&highlight=3)]
|
|
|
|
The parameterless `UseStaticFiles` method overload marks the files in web root as servable. The following markup references *wwwroot/images/banner1.svg*:
|
|
|
|
[!code-cshtml[](static-files/samples/1x/Views/Home/Index.cshtml?name=snippet_static_file_wwwroot)]
|
|
|
|
### Serve files outside of web root
|
|
|
|
Consider a directory hierarchy in which the static files to be served reside outside of the web root:
|
|
|
|
* **wwwroot**
|
|
* **css**
|
|
* **images**
|
|
* **js**
|
|
* **MyStaticFiles**
|
|
* **images**
|
|
* *banner1.svg*
|
|
|
|
A request can access the *banner1.svg* file by configuring the static file middleware as follows:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupTwoStaticFiles.cs?name=snippet_ConfigureMethod&highlight=5-10)]
|
|
|
|
In the preceding code, the *MyStaticFiles* directory hierarchy is exposed publicly via the *StaticFiles* URI segment. A request to *http://\<server_address>/StaticFiles/images/banner1.svg* serves the *banner1.svg* file.
|
|
|
|
The following markup references *MyStaticFiles/images/banner1.svg*:
|
|
|
|
[!code-cshtml[](static-files/samples/1x/Views/Home/Index.cshtml?name=snippet_static_file_outside)]
|
|
|
|
### Set HTTP response headers
|
|
|
|
A [StaticFileOptions](/dotnet/api/microsoft.aspnetcore.builder.staticfileoptions) object can be used to set HTTP response headers. In addition to configuring static file serving from the web root, the following code sets the `Cache-Control` header:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupAddHeader.cs?name=snippet_ConfigureMethod)]
|
|
|
|
The [HeaderDictionaryExtensions.Append](/dotnet/api/microsoft.aspnetcore.http.headerdictionaryextensions.append) method exists in the [Microsoft.AspNetCore.Http](https://www.nuget.org/packages/Microsoft.AspNetCore.Http/) package.
|
|
|
|
The files have been made publicly cacheable for 10 minutes (600 seconds):
|
|
|
|
![Response headers showing the Cache-Control header has been added](static-files/_static/add-header.png)
|
|
|
|
## Static file authorization
|
|
|
|
The static file middleware doesn't provide authorization checks. Any files served by it, including those under *wwwroot*, are publicly accessible. To serve files based on authorization:
|
|
|
|
* Store them outside of *wwwroot* and any directory accessible to the static file middleware **and**
|
|
* Serve them via an action method to which authorization is applied. Return a [FileResult](/dotnet/api/microsoft.aspnetcore.mvc.fileresult) object:
|
|
|
|
[!code-csharp[](static-files/samples/1x/Controllers/HomeController.cs?name=snippet_BannerImageAction)]
|
|
|
|
## 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](#considerations)). Enable directory browsing by invoking the [UseDirectoryBrowser](/dotnet/api/microsoft.aspnetcore.builder.directorybrowserextensions.usedirectorybrowser#Microsoft_AspNetCore_Builder_DirectoryBrowserExtensions_UseDirectoryBrowser_Microsoft_AspNetCore_Builder_IApplicationBuilder_Microsoft_AspNetCore_Builder_DirectoryBrowserOptions_) method in `Startup.Configure`:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupBrowse.cs?name=snippet_ConfigureMethod&highlight=12-17)]
|
|
|
|
Add required services by invoking the [AddDirectoryBrowser](/dotnet/api/microsoft.extensions.dependencyinjection.directorybrowserserviceextensions.adddirectorybrowser#Microsoft_Extensions_DependencyInjection_DirectoryBrowserServiceExtensions_AddDirectoryBrowser_Microsoft_Extensions_DependencyInjection_IServiceCollection_) method from `Startup.ConfigureServices`:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupBrowse.cs?name=snippet_ConfigureServicesMethod&highlight=3)]
|
|
|
|
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:
|
|
|
|
![directory browsing](static-files/_static/dir-browse.png)
|
|
|
|
See [Considerations](#considerations) on the security risks when enabling browsing.
|
|
|
|
Note the two `UseStaticFiles` calls in the following example. The first call enables the serving of static files in the *wwwroot* folder. The second call enables directory browsing of the *wwwroot/images* folder using the URL *http://\<server_address>/MyImages*:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupBrowse.cs?name=snippet_ConfigureMethod&highlight=3,5)]
|
|
|
|
## Serve a default document
|
|
|
|
Setting a default home page provides visitors a logical starting point when visiting your site. To serve a default page without the user fully qualifying the URI, call the [UseDefaultFiles](/dotnet/api/microsoft.aspnetcore.builder.defaultfilesextensions.usedefaultfiles#Microsoft_AspNetCore_Builder_DefaultFilesExtensions_UseDefaultFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_) method from `Startup.Configure`:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupEmpty.cs?name=snippet_ConfigureMethod&highlight=3)]
|
|
|
|
> [!IMPORTANT]
|
|
> `UseDefaultFiles` must be called before `UseStaticFiles` to serve the default file. `UseDefaultFiles` is a URL rewriter that doesn't actually serve the file. Enable the static file middleware via `UseStaticFiles` to serve the file.
|
|
|
|
With `UseDefaultFiles`, requests to a folder search for:
|
|
|
|
* *default.htm*
|
|
* *default.html*
|
|
* *index.htm*
|
|
* *index.html*
|
|
|
|
The first file found from the list is served as though the request were the fully qualified URI. The browser URL continues to reflect the URI requested.
|
|
|
|
The following code changes the default file name to *mydefault.html*:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupDefault.cs?name=snippet_ConfigureMethod)]
|
|
|
|
## UseFileServer
|
|
|
|
[UseFileServer](/dotnet/api/microsoft.aspnetcore.builder.fileserverextensions.usefileserver#Microsoft_AspNetCore_Builder_FileServerExtensions_UseFileServer_Microsoft_AspNetCore_Builder_IApplicationBuilder_) 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.
|
|
|
|
```csharp
|
|
app.UseFileServer();
|
|
```
|
|
|
|
The following code builds upon the parameterless overload by enabling directory browsing:
|
|
|
|
```csharp
|
|
app.UseFileServer(enableDirectoryBrowsing: true);
|
|
```
|
|
|
|
Consider the following directory hierarchy:
|
|
|
|
* **wwwroot**
|
|
* **css**
|
|
* **images**
|
|
* **js**
|
|
* **MyStaticFiles**
|
|
* **images**
|
|
* *banner1.svg*
|
|
* *default.html*
|
|
|
|
The following code enables static files, default files, and directory browsing of `MyStaticFiles`:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupUseFileServer.cs?name=snippet_ConfigureMethod&highlight=5-11)]
|
|
|
|
`AddDirectoryBrowser` must be called when the `EnableDirectoryBrowsing` property value is `true`:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupUseFileServer.cs?name=snippet_ConfigureServicesMethod)]
|
|
|
|
Using the file hierarchy and preceding code, URLs resolve as follows:
|
|
|
|
| URI | Response |
|
|
| ------- | ------|
|
|
| *http://\<server_address>/StaticFiles/images/banner1.svg* | MyStaticFiles/images/banner1.svg |
|
|
| *http://\<server_address>/StaticFiles* | MyStaticFiles/default.html |
|
|
|
|
If no default-named file exists in the *MyStaticFiles* directory, *http://\<server_address>/StaticFiles* returns the directory listing with clickable links:
|
|
|
|
![Static files list](static-files/_static/db2.png)
|
|
|
|
> [!NOTE]
|
|
> `UseDefaultFiles` and `UseDirectoryBrowser` use the URL *http://\<server_address>/StaticFiles* without the trailing slash to trigger a client-side redirect to *http://\<server_address>/StaticFiles/*. Notice the addition of the trailing slash. Relative URLs within the documents are deemed invalid without a trailing slash.
|
|
|
|
## FileExtensionContentTypeProvider
|
|
|
|
The [FileExtensionContentTypeProvider](/dotnet/api/microsoft.aspnetcore.staticfiles.fileextensioncontenttypeprovider) class contains a `Mappings` property serving as a mapping of file extensions to MIME content types. In the following sample, several file extensions are registered to known MIME types. The *.rtf* extension is replaced, and *.mp4* is removed.
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupFileExtensionContentTypeProvider.cs?name=snippet_ConfigureMethod&highlight=3-12,19)]
|
|
|
|
See [MIME content types](http://www.iana.org/assignments/media-types/media-types.xhtml).
|
|
|
|
## Non-standard content types
|
|
|
|
The static file middleware understands almost 400 known file content types. If the user requests a file of an unknown file type, the static file middleware returns a HTTP 404 (Not Found) response. If directory browsing is enabled, a link to the file is displayed. The URI returns an HTTP 404 error.
|
|
|
|
The following code enables serving unknown types and renders the unknown file as an image:
|
|
|
|
[!code-csharp[](static-files/samples/1x/StartupServeUnknownFileTypes.cs?name=snippet_ConfigureMethod)]
|
|
|
|
With the preceding code, a request for a file with an unknown content type is returned as an image.
|
|
|
|
> [!WARNING]
|
|
> Enabling [ServeUnknownFileTypes](/dotnet/api/microsoft.aspnetcore.builder.staticfileoptions.serveunknownfiletypes#Microsoft_AspNetCore_Builder_StaticFileOptions_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
|
|
|
|
> [!WARNING]
|
|
> `UseDirectoryBrowser` and `UseStaticFiles` can leak secrets. Disabling directory browsing in production is highly recommended. Carefully review which directories are enabled via `UseStaticFiles` or `UseDirectoryBrowser`. The entire directory and its sub-directories become publicly accessible. Store files suitable for serving to the public in a dedicated directory, such as *\<content_root>/wwwroot*. Separate these files from MVC views, Razor Pages (2.x only), configuration files, etc.
|
|
|
|
* The URLs for content exposed with `UseDirectoryBrowser` and `UseStaticFiles` are subject to the case sensitivity and character restrictions of the underlying file system. For example, Windows is case insensitive—Mac and Linux aren't.
|
|
|
|
* ASP.NET Core apps hosted in IIS use the [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module) to forward all requests to the app, including static file requests. The IIS static file handler isn't used. It has no chance to handle requests before they're handled by the module.
|
|
|
|
* 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.
|
|
1. Select **StaticFileModule** in the list.
|
|
1. Click **Remove** in the **Actions** sidebar.
|
|
|
|
> [!WARNING]
|
|
> If the IIS static file handler is enabled **and** the ASP.NET Core Module is configured incorrectly, static files are served. This happens, for example, if the *web.config* file isn't deployed.
|
|
|
|
* 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
|
|
|
|
* [Middleware](xref:fundamentals/middleware/index)
|
|
* [Introduction to ASP.NET Core](xref:index)
|