Archivos estáticos en ASP.NET Core

Por Rick Anderson y Kirk Larkin

Los archivos estáticos, como HTML, CSS, imágenes y JavaScript, son activos que una aplicación de ASP.NET Core proporciona directamente a los clientes de forma predeterminada.

Vea o descargue el código de ejemplo (cómo descargarlo)

Proporcionar archivos estáticos

Los archivos estáticos se almacenan en el directorio raíz web del proyecto. El directorio predeterminado es {content root}/wwwroot, pero se puede cambiar con el método UseWebRoot. Para más información, vea Raíz del contenido y Raíz web.

El método CreateDefaultBuilder establece la raíz de contenido en el directorio actual:

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

El código anterior se creó con la plantilla de la aplicación web.

Se puede acceder a los archivos estáticos a través de una ruta de acceso relativa a la raíz web. Por ejemplo, las plantillas de proyecto Aplicación web contienen varias carpetas dentro de la carpeta wwwroot:

  • wwwroot
    • css
    • js
    • lib

Considere la posibilidad de crear la carpeta wwwroot/images y agregar el archivo wwwroot/images/MyImage.jpg. El formato del URI para acceder a un archivo en la carpeta images es https://<hostname>/images/<image_file_name>. Por ejemplo, https://localhost:5001/images/MyImage.jpg.

Suministro de archivos en la raíz web

Las plantillas de aplicación web predeterminadas llaman al método UseStaticFiles en Startup.Configure, que permite proporcionar archivos estáticos:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

La sobrecarga del método UseStaticFiles sin parámetros marca los archivos en la raíz web como que se pueden proporcionar. El siguiente marcado hace referencia a wwwroot/images/MyImage.jpg:

<img src="~/images/MyImage.jpg" class="img" alt="My image" />

En el código anterior, el carácter de tilde de la ñ ~/ apunta a la raíz web.

Proporcionar archivos fuera de la raíz web

Considere una jerarquía de directorios en la que residen fuera de la raíz web los archivos estáticos que se van a proporcionar:

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • images
      • red-rose.jpg

Una solicitud puede acceder al archivo red-rose.jpg configurando el middleware de archivos estáticos como se muestra a continuación:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    // using Microsoft.Extensions.FileProviders;
    // using System.IO;
    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(env.ContentRootPath, "MyStaticFiles")),
        RequestPath = "/StaticFiles"
    });

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

En el código anterior, la jerarquía del directorio MyStaticFiles se expone públicamente a través del segmento de URI StaticFiles. Una solicitud a https://<hostname>/StaticFiles/images/red-rose.jpg sirve al archivo red-rose.jpg.

El siguiente marcado hace referencia a MyStaticFiles/images/red-rose.jpg:

<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />

Establecer encabezados de respuesta HTTP

Se puede usar un objeto StaticFileOptions para establecer encabezados de respuesta HTTP. Además de configurar el servicio de archivos estáticos desde la raíz web, el código siguiente establece el encabezado Cache-Control:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    const string cacheMaxAge = "604800";
    app.UseStaticFiles(new StaticFileOptions
    {
        OnPrepareResponse = ctx =>
        {
            // using Microsoft.AspNetCore.Http;
            ctx.Context.Response.Headers.Append(
                 "Cache-Control", $"public, max-age={cacheMaxAge}");
        }
    });

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

Los archivos estáticos se almacenan en caché públicamente durante 600 segundos:

Se han agregado encabezados de respuesta que muestran el encabezado Cache-Control

Autorización de archivos estáticos

Las plantillas de ASP.NET Core llaman a UseStaticFiles antes de llamar a UseAuthorization. La mayoría de las aplicaciones siguen este patrón. Cuando se llama al middleware de archivos estáticos antes de al middleware de autorización:

  • No se realizan comprobaciones de autorización en los archivos estáticos.
  • Los archivos estáticos que atiende el middleware de archivos estáticos, como los que están en wwwroot, son accesibles públicamente.

Para proporcionar archivos estáticos según su autorización:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    // wwwroot css, JavaScript, and images don't require authentication.
    app.UseStaticFiles();   

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddRazorPages();

        services.AddAuthorization(options =>
        {
            options.FallbackPolicy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
        });
    }

    // Remaining code ommitted for brevity.

En el código anterior, la directiva de autorización de reserva requiere que se autentiquen todos los usuarios. Los puntos de conexión como los controladores, Razor Pages, etc. que especifican sus propios requisitos de autorización no usan la directiva de autorización de reserva. Por ejemplo, Razor Pages, controladores o métodos de acción con [AllowAnonymous] o [Authorize(PolicyName="MyPolicy")] usan el atributo de autorización aplicado en lugar de la directiva de autorización de reserva.

RequireAuthenticatedUser agrega DenyAnonymousAuthorizationRequirement a la instancia actual, lo que exige que el usuario actual se autentique.

Los recursos estáticos en wwwroot son accesibles públicamente porque se llama al middleware de archivos estáticos predeterminado (app.UseStaticFiles();) antes de a UseAuthentication. Los recursos estáticos de la carpeta MyStaticFiles requieren autenticación. En el código de ejemplo se muestra esto.

Un enfoque alternativo a proporcionar archivos según la autorización es:

  • Almacénelos fuera de wwwroot y cualquier directorio al que el middleware de archivos estáticos tenga acceso.
  • Proporciónelos a través de un método de acción al que se aplica la autorización y devuelva un objeto FileResult:
[Authorize]
public IActionResult BannerImage()
{
    var filePath = Path.Combine(
        _env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");

    return PhysicalFile(filePath, "image/jpeg");
}

Examen de directorios

El examen de directorios permite enumerar directorios dentro de los directorios especificados.

Por motivos de seguridad, el examen de directorios está deshabilitado de forma predeterminada. Para obtener más información, consulte Consideraciones de seguridad para archivos estáticos.

Habilite el examen de directorios con:

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

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    // using Microsoft.Extensions.FileProviders;
    // using System.IO;
    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(env.WebRootPath, "images")),
        RequestPath = "/MyImages"
    });

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

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

El código anterior permite el examen de directorios de la carpeta wwwroot/images usando la dirección URL https://<hostname>/MyImages, con vínculos a cada archivo y carpeta:

examen de directorios

Suministro de documentos predeterminados

El establecimiento de una página predeterminada proporciona a los visitantes un punto inicial en un sitio. Para servir un archivo predeterminado desde wwwroot sin necesidad de que la dirección URL de la solicitud incluya el nombre del archivo, llame al método UseDefaultFiles:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    app.UseDefaultFiles();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

Debe llamarse a UseDefaultFiles antes de a UseStaticFiles para proporcionar el archivo predeterminado. UseDefaultFiles es un sistema de reescritura de direcciones URL que no proporciona el archivo.

Con UseDefaultFiles, las solicitudes a una carpeta en wwwroot buscan:

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

El primer archivo que se encuentra en la lista se sirve como si la solicitud incluyera el nombre de archivo. La dirección URL del explorador sigue reflejando el URI solicitado.

El código siguiente cambia el nombre de archivo predeterminado a mydefault.html:

var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();

El código siguiente muestra Startup.Configure con el código anterior:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    var options = new DefaultFilesOptions();
    options.DefaultFileNames.Clear();
    options.DefaultFileNames.Add("mydefault.html");
    app.UseDefaultFiles(options);
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

UseFileServer para documentos predeterminados

UseFileServer combina la funcionalidad de UseStaticFiles y UseDefaultFiles y, opcionalmente, la de UseDirectoryBrowser.

Llame a app.UseFileServer para poder proporcionar archivos estáticos y el archivo predeterminado. El examen de directorios no está habilitado. El código siguiente muestra Startup.Configure con UseFileServer:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    app.UseFileServer();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

El código siguiente permite proporcionar archivos estáticos, el archivo predeterminado y el examen de directorios:

app.UseFileServer(enableDirectoryBrowsing: true);

El código siguiente muestra Startup.Configure con el código anterior:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    app.UseFileServer(enableDirectoryBrowsing: true);

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

Tenga en cuenta la siguiente jerarquía de directorios:

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • images
      • MyImage.jpg
    • default.html

El código siguiente permite proporcionar archivos estáticos, el archivo predeterminado y el examen de directorios de MyStaticFiles:

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

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    app.UseStaticFiles(); // For the wwwroot folder.

    // using Microsoft.Extensions.FileProviders;
    // using System.IO;
    app.UseFileServer(new FileServerOptions
    {
        FileProvider = new PhysicalFileProvider(
            Path.Combine(env.ContentRootPath, "MyStaticFiles")),
        RequestPath = "/StaticFiles",
        EnableDirectoryBrowsing = true
    });

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

Se debe llamar a AddDirectoryBrowser cuando el valor de la propiedad EnableDirectoryBrowsing es true.

Al usar la jerarquía de archivos y el código anterior, las direcciones URL se resuelven como se indica a continuación:

Identificador URI Respuesta
https://<hostname>/StaticFiles/images/MyImage.jpg MyStaticFiles/images/MyImage.jpg
https://<hostname>/StaticFiles MyStaticFiles/default.html

Si no existe ningún archivo con el nombre predeterminado en el directorio MyStaticFiles, https://<hostname>/StaticFiles devuelve la lista de directorios con vínculos activos:

Lista de archivos estáticos

UseDefaultFiles y UseDirectoryBrowser realizan un redireccionamiento del lado cliente desde el URI de destino sin una / final hasta el URI de destino una / final. Por ejemplo, desde https://<hostname>/StaticFiles hasta https://<hostname>/StaticFiles/. Las direcciones URL relativas dentro del directorio StaticFiles no son válidas sin una barra diagonal final (/).

FileExtensionContentTypeProvider

La clase FileExtensionContentTypeProvider contiene una propiedad Mappings que actúa como una asignación de extensiones de archivo para tipos de contenido MIME. En el ejemplo siguiente, se asignan varias extensiones de archivo a los tipos MIME conocidos. Se reemplaza la extensión .rtf y se quita .mp4:

// using Microsoft.AspNetCore.StaticFiles;
// using Microsoft.Extensions.FileProviders;
// using System.IO;

// 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(env.WebRootPath, "images")),
    RequestPath = "/MyImages",
    ContentTypeProvider = provider
});

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

El código siguiente muestra Startup.Configure con el código anterior:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    // using Microsoft.AspNetCore.StaticFiles;
    // using Microsoft.Extensions.FileProviders;
    // using System.IO;

    // 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(env.WebRootPath, "images")),
        RequestPath = "/MyImages",
        ContentTypeProvider = provider
    });

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

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

Vea Tipos de contenido MIME.

Tipos de contenido no estándar

El middleware de archivos estáticos entiende casi 400 tipos de contenido de archivo conocidos. Si el usuario solicita un archivo con un tipo de archivo desconocido, el middleware de archivos estáticos pasa la solicitud al siguiente middleware de la canalización. Si ningún middleware se ocupa de la solicitud, se devuelve una respuesta 404 No encontrado. Si se habilita la exploración de directorios, se muestra un vínculo al archivo en una lista de directorios.

El código siguiente permite proporcionar tipos desconocidos y procesa el archivo desconocido como una imagen:

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

El código siguiente muestra Startup.Configure con el código anterior:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();

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

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

Con el código anterior, una solicitud para un archivo con un tipo de contenido desconocido se devuelve como una imagen.

Advertencia

Habilitar ServeUnknownFileTypes supone un riesgo para la seguridad. Está deshabilitado de forma predeterminada y no se recomienda su uso. FileExtensionContentTypeProvider proporciona una alternativa más segura a ofrecer archivos con extensiones no estándar.

Entrega de archivos desde varias ubicaciones

UseStaticFiles y UseFileServer tienen como valor predeterminado el proveedor de archivos que apunta a wwwroot. Se pueden proporcionar instancias adicionales de UseStaticFiles y UseFileServer con otros proveedores de archivos para proporcionar archivos desde otras ubicaciones. Para más información, consulte este problema de GitHub.

Consideraciones de seguridad para archivos estáticos

Advertencia

UseDirectoryBrowser y UseStaticFiles pueden producir pérdidas de información confidencial. Se recomienda deshabilitar el examen de directorios en producción. Revise cuidadosamente los directorios que se habilitan mediante UseStaticFiles o UseDirectoryBrowser. Todo el directorio y sus subdirectorios pasan a ser accesibles públicamente. Almacene los archivos adecuados para proporcionarlos al público en un directorio dedicado, como <content_root>/wwwroot. Separe estos archivos de las vistas MVC, de Razor Pages, de los archivos de configuración, etc.

  • Las direcciones URL para el contenido que se expone a través de UseDirectoryBrowser y UseStaticFiles están sujetas a la distinción entre mayúsculas y minúsculas, y a restricciones de caracteres del sistema de archivos subyacente. Por ejemplo, Windows no distingue entre mayúsculas y minúsculas, pero macOS y Linux sí.

  • Las aplicaciones de ASP.NET Core hospedadas en IIS usan el módulo de ASP.NET Core para reenviar todas las solicitudes a la aplicación, incluidas las solicitudes de archivos estáticos. No se utiliza el controlador de archivos estáticos de IIS y no tiene la posibilidad de controlar las solicitudes.

  • Complete los pasos siguientes en el Administrador de IIS para quitar el controlador de archivos estáticos de IIS en el nivel de servidor o de sitio web:

    1. Navegue hasta la característica Módulos.
    2. En la lista, seleccione StaticFileModule.
    3. Haga clic en Quitar en la barra lateral Acciones.

Advertencia

Si el controlador de archivos estáticos de IIS está habilitado y el módulo de ASP.NET Core no está configurado correctamente, se proporcionan archivos estáticos. Esto sucede, por ejemplo, si el archivo web.config no está implementado.

  • Coloque los archivos de código (incluidos .cs y .cshtml) fuera de la raíz web del proyecto de la aplicación. Por lo tanto, se crea una separación lógica entre el contenido del lado cliente de la aplicación y el código basado en servidor. Esto impide que se filtre el código del lado servidor.

Recursos adicionales

Por Rick Anderson y Scott Addie

Los archivos estáticos, como HTML, CSS, imágenes y JavaScript, son activos que una aplicación de ASP.NET Core proporciona directamente a los clientes. Se necesita alguna configuración para habilitar el servicio de estos archivos.

Vea o descargue el código de ejemplo (cómo descargarlo)

Proporcionar archivos estáticos

Los archivos estáticos se almacenan en el directorio raíz web del proyecto. El directorio predeterminado es {raíz del contenido}/wwwroot, pero se puede cambiar con el método UseWebRoot. Vea Raíz del contenido y Raíz web para obtener más información.

El host de web de la aplicación debe tener conocimiento del directorio raíz del contenido.

El método WebHost.CreateDefaultBuilder establece la raíz de contenido en el directorio actual:

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

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

Se puede acceder a los archivos estáticos a través de una ruta de acceso relativa a la raíz web. Por ejemplo, la plantilla de proyecto Aplicación web contiene varias carpetas dentro de la carpeta wwwroot:

  • wwwroot
    • css
    • images
    • js

El formato de URI para acceder a un archivo en la subcarpeta images es http://<server_address>/images/<image_file_name> . Por ejemplo, http://localhost:9189/images/banner3.svg .

Si el destino es .NET Framework, agregue el paquete Microsoft.AspNetCore.StaticFiles al proyecto. Si el destino es .NET Core, el metapaquete Microsoft.AspNetCore.App incluye este paquete.

Configure el middleware, que permite proporcionar archivos estáticos.

Proporcionar archivos dentro de la raíz web

Invoque al método UseStaticFiles en Startup.Configure:

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

La sobrecarga del método UseStaticFiles sin parámetros marca los archivos en la raíz web como que se pueden proporcionar. El siguiente marcado hace referencia a wwwroot/images/banner1.svg:

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

En el código anterior, el carácter de tilde de la ñ ~/ apunta a la raíz web.

Proporcionar archivos fuera de la raíz web

Considere una jerarquía de directorios en la que residen fuera de la raíz web los archivos estáticos que se van a proporcionar:

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • images
      • banner1.svg

Una solicitud puede acceder al archivo banner1.svg configurando el middleware de archivos estáticos como se muestra a continuación:

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"
    });
}

En el código anterior, la jerarquía del directorio MyStaticFiles se expone públicamente a través del segmento de URI StaticFiles. Una solicitud a http://<server_address>/StaticFiles/images/banner1.svg proporciona el archivo banner1.svg.

El siguiente marcado hace referencia a MyStaticFiles/images/banner1.svg:

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

Establecer encabezados de respuesta HTTP

Se puede usar un objeto StaticFileOptions para establecer encabezados de respuesta HTTP. Además de configurar el servicio de archivos estáticos desde la raíz web, el código siguiente establece el encabezado Cache-Control:

public void Configure(IApplicationBuilder app)
{
    var cachePeriod =  "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}");
        }
    });
}

Si quiere que los comentarios de código se traduzcan en más idiomas además del inglés, háganoslo saber en este problema de debate de GitHub.

El método HeaderDictionaryExtensions.Append existe en el paquete Microsoft.AspNetCore.Http.

Los archivos se han hecho públicamente almacenables en caché durante 10 minutos (600 segundos) en el entorno de desarrollo:

Se han agregado encabezados de respuesta que muestran el encabezado Cache-Control

Autorización de archivos estáticos

El middleware de archivos estáticos no proporciona comprobaciones de autorización. Los archivos que proporciona, incluidos los de wwwroot, están accesibles de forma pública. Para proporcionar archivos según su autorización:

  • Almacénelos fuera de wwwroot y cualquier directorio al que el middleware de archivos estáticos tenga acceso.

  • Proporciónelos a través de un método de acción al que se aplica la autorización. Devuelva un objeto FileResult:

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

Habilite el examen de directorios

El examen de directorios permite a los usuarios de su aplicación web ver una lista de directorios y archivos contenidos en un directorio especificado. Por motivos de seguridad, el examen de directorios está deshabilitado de forma predeterminada (consulte Consideraciones). Habilite el examen de directorios invocando el método UseDirectoryBrowser en 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"
    });
}

Agregar servicios requeridos invocando el método AddDirectoryBrowser desde Startup.ConfigureServices:

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

El código anterior permite el examen de directorios de la carpeta wwwroot/images usando la dirección URL http://<server_address>/MyImages, con vínculos a cada archivo y carpeta:

examen de directorios

Vea consideraciones sobre los riesgos de seguridad al habilitar el examen.

Tenga en cuenta las dos llamadas a UseStaticFiles en el ejemplo siguiente. La primera llamada permite proporcionar archivos estáticos en la carpeta wwwroot. La segunda llamada habilita el examen de directorios de la carpeta wwwroot/images usando la dirección 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"
    });
}

Proporcionar un documento predeterminado

Establecer una página principal predeterminada proporciona a los visitantes un punto de partida lógico cuando visitan su sitio. Para proporcionar una página predeterminada sin que el usuario cumpla por completo los requisitos del URI, llame al método UseDefaultFiles desde Startup.Configure:

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

Importante

Debe llamarse a UseDefaultFiles antes de a UseStaticFiles para proporcionar el archivo predeterminado. UseDefaultFiles es un sistema de reescritura de direcciones URL que no proporciona realmente el archivo. Habilite el middleware de archivos estáticos a través de UseStaticFiles para proporcionar el archivo.

Con UseDefaultFiles, las solicitudes a una carpeta buscan:

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

El primer archivo que se encuentra en la lista se proporciona como si la solicitud fuera el URI completo. La dirección URL del explorador sigue reflejando el URI solicitado.

El código siguiente cambia el nombre de archivo predeterminado a 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

UseFileServer combina la funcionalidad de UseStaticFiles y UseDefaultFiles y, opcionalmente, la de UseDirectoryBrowser.

El código siguiente permite proporcionar archivos estáticos y el archivo predeterminado. El examen de directorios no está habilitado.

app.UseFileServer();

El código siguiente refuerza la sobrecarga sin parámetros habilitando el examen de directorios:

app.UseFileServer(enableDirectoryBrowsing: true);

Tenga en cuenta la siguiente jerarquía de directorios:

  • wwwroot
    • css
    • images
    • js
  • MyStaticFiles
    • images
      • banner1.svg
    • default.html

El código siguiente permite los archivos estáticos, los archivos predeterminados y el examen de directorios de 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
    });
}

Se debe llamar a AddDirectoryBrowser cuando el valor de la propiedad EnableDirectoryBrowsing es true:

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

Al usar la jerarquía de archivos y el código anterior, las direcciones URL se resuelven como se indica a continuación:

Identificador URI Respuesta
http://<server_address>/StaticFiles/images/banner1.svg MyStaticFiles/images/banner1.svg
http://<server_address>/StaticFiles MyStaticFiles/default.html

Si no existe ningún archivo con el nombre predeterminado en el directorio MyStaticFiles, http://<server_address>/StaticFiles devuelve la lista de directorios con vínculos activos:

Lista de archivos estáticos

Nota

UseDefaultFiles y UseDirectoryBrowser realizan un redireccionamiento del lado cliente desde http://{SERVER ADDRESS}/StaticFiles (sin una barra diagonal final) hasta http://{SERVER ADDRESS}/StaticFiles/ (con una barra diagonal final). Las direcciones URL relativas dentro del directorio StaticFiles no son válidas sin una barra diagonal final.

FileExtensionContentTypeProvider

La clase FileExtensionContentTypeProvider contiene una propiedad Mappings que actúa como una asignación de extensiones de archivo para tipos de contenido MIME. En el ejemplo siguiente, se registran varias extensiones de archivo a los tipos MIME conocidos. Se reemplaza la extensión .rtf y se quita .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 = "/MyImages",
        ContentTypeProvider = provider
    });

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

Vea Tipos de contenido MIME.

Para obtener información sobre el uso de un objeto FileExtensionContentTypeProvider personalizado o para configurar otras instancias de StaticFileOptions en aplicaciones Blazor Server, vea Archivos estáticos Blazor en ASP.NET Core.

Tipos de contenido no estándar

El middleware de archivos estáticos entiende casi 400 tipos de contenido de archivo conocidos. Si el usuario solicita un archivo con un tipo de archivo desconocido, el middleware de archivos estáticos pasa la solicitud al siguiente middleware de la canalización. Si ningún middleware se ocupa de la solicitud, se devuelve una respuesta 404 No encontrado. Si se habilita la exploración de directorios, se muestra un vínculo al archivo en una lista de directorios.

El código siguiente permite proporcionar tipos desconocidos y procesa el archivo desconocido como una imagen:

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

Con el código anterior, una solicitud para un archivo con un tipo de contenido desconocido se devuelve como una imagen.

Advertencia

Habilitar ServeUnknownFileTypes supone un riesgo para la seguridad. Está deshabilitado de forma predeterminada y no se recomienda su uso. FileExtensionContentTypeProvider proporciona una alternativa más segura a ofrecer archivos con extensiones no estándar.

Entrega de archivos desde varias ubicaciones

UseStaticFiles y UseFileServer tienen como valor predeterminado el proveedor de archivos que apunta a wwwroot. Puede proporcionar instancias adicionales de UseStaticFiles y UseFileServer con otros proveedores de archivos para proporcionar archivos desde otras ubicaciones. Para más información, consulte este problema de GitHub.

Consideraciones

Advertencia

UseDirectoryBrowser y UseStaticFiles pueden producir pérdidas de información confidencial. Se recomienda deshabilitar el examen de directorios en producción. Revise cuidadosamente los directorios que se habilitan mediante UseStaticFiles o UseDirectoryBrowser. Todo el directorio y sus subdirectorios pasan a ser accesibles públicamente. Almacene los archivos adecuados para proporcionarlos al público en un directorio dedicado, como <content_root>/wwwroot. Separe estos archivos de las vistas MVC, las instancias de Razor Pages (solo 2.x), los archivos de configuración, etc.

  • Las direcciones URL para el contenido que se expone a través de UseDirectoryBrowser y UseStaticFiles están sujetas a la distinción entre mayúsculas y minúsculas, y a restricciones de caracteres del sistema de archivos subyacente. Por ejemplo, Windows no distingue entre mayúsculas y minúsculas, pero macOS y Linux sí.

  • Las aplicaciones de ASP.NET Core hospedadas en IIS usan el módulo de ASP.NET Core para reenviar todas las solicitudes a la aplicación, incluidas las solicitudes de archivos estáticos. No se usa el controlador de archivos estáticos de IIS. No tiene ninguna posibilidad de controlar las solicitudes antes de que las controle el módulo.

  • Complete los pasos siguientes en el Administrador de IIS para quitar el controlador de archivos estáticos de IIS en el nivel de servidor o de sitio web:

    1. Navegue hasta la característica Módulos.
    2. En la lista, seleccione StaticFileModule.
    3. Haga clic en Quitar en la barra lateral Acciones.

Advertencia

Si el controlador de archivos estáticos de IIS está habilitado y el módulo de ASP.NET Core no está configurado correctamente, se proporcionan archivos estáticos. Esto sucede, por ejemplo, si el archivo web.config no está implementado.

  • Coloque los archivos de código (incluidos .cs y .cshtml) fuera de la raíz web del proyecto de la aplicación. Por lo tanto, se crea una separación lógica entre el contenido del lado cliente de la aplicación y el código basado en servidor. Esto impide que se filtre el código del lado servidor.

Recursos adicionales