Proveedores de archivo en ASP.NET Core
Nota:
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la directiva de compatibilidad de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Importante
Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
Para la versión actual, consulte la versión de .NET 9 de este artículo.
Por Steve Smith
ASP.NET Core abstrae el acceso al sistema de archivos mediante el uso de proveedores de archivos. Los proveedores de archivos se usan en el marco de ASP.NET Core. Por ejemplo:
- IWebHostEnvironment expone la raíz del contenido y la raíz web de la aplicación como tipos
IFileProvider
. - El middleware de archivos estáticos usa proveedores de archivos para buscar archivos estáticos.
- Razor usa proveedores de archivos para localizar páginas y vistas.
- Las herramientas de .NET Core usan proveedores de archivos y patrones globales para especificar los archivos que deben publicarse.
Vea o descargue el código de ejemplo (cómo descargarlo)
Interfaces de proveedor de archivos
La interfaz principal es IFileProvider. IFileProvider
expone métodos para:
- Obtenga la información del archivo (IFileInfo).
- Obtenga la información del directorio (IDirectoryContents).
- Configure las notificaciones de cambio (mediante IChangeToken).
IFileInfo
proporciona métodos y propiedades para trabajar con archivos:
- Exists
- IsDirectory
- Name
- Length (en bytes)
- Fecha LastModified
Se puede leer en el archivo mediante el método IFileInfo.CreateReadStream.
La aplicación de ejemplo FileProviderSample
muestra cómo configurar un proveedor de archivos en Startup.ConfigureServices
para su uso en toda la aplicación a través de la inserción de dependencias.
Implementaciones del proveedor de archivos
En la tabla siguiente se enumeran las implementaciones de IFileProvider
.
Implementación | Descripción |
---|---|
Proveedor de archivos compuestos | Se usa para proporcionar acceso combinado a archivos y directorios de uno o más proveedores. |
Proveedor de archivos incrustados de manifiesto | Se usa para tener acceso a archivos insertados en ensamblados. |
Proveedor de archivos físicos | Se usa para tener acceso a los archivos físicos del sistema. |
Proveedor de archivos físicos
PhysicalFileProvider proporciona acceso al sistema de archivos físico. PhysicalFileProvider
usa el tipo System.IO.File (para el proveedor físico) y define el ámbito de todas las rutas de acceso a un directorio y sus elementos secundarios. Esta definición de ámbito impide el acceso al sistema de archivos fuera del directorio especificado y sus elementos secundarios. El escenario más común para crear y usar PhysicalFileProvider
es solicitar IFileProvider
en un constructor mediante la inyección de dependencias.
Al crear una instancia de este proveedor directamente, se requiere una ruta de acceso absoluta al directorio, que actúa como la ruta de acceso base para todas las solicitudes realizadas usando el proveedor. Los patrones globales no se admiten en la ruta de acceso al directorio.
El código siguiente muestra cómo usar PhysicalFileProvider
para obtener el contenido del directorio y la información del archivo:
var provider = new PhysicalFileProvider(applicationRoot);
var contents = provider.GetDirectoryContents(string.Empty);
var filePath = Path.Combine("wwwroot", "js", "site.js");
var fileInfo = provider.GetFileInfo(filePath);
Tipos del ejemplo anterior:
provider
esIFileProvider
.contents
esIDirectoryContents
.fileInfo
esIFileInfo
.
El proveedor de archivos puede usarse para iterar por el directorio especificado por applicationRoot
o llamar a GetFileInfo
para obtener información de un archivo. No se pueden pasar patrones globales al método GetFileInfo
. El proveedor de archivos no tiene acceso fuera del directorio applicationRoot
.
La aplicación de ejemplo FileProviderSample
crea el proveedor en el método Startup.ConfigureServices
con IHostEnvironment.ContentRootFileProvider:
var physicalProvider = _env.ContentRootFileProvider;
Proveedor de archivos incrustados de manifiesto
ManifestEmbeddedFileProvider se utiliza para acceder a archivos insertados dentro de ensamblados. ManifestEmbeddedFileProvider
utiliza un manifiesto compilado en el ensamblado para reconstruir las rutas de acceso originales de los archivos incrustados.
Para generar un manifiesto de los archivos incrustados:
Agregue el paquete NuGet
Microsoft.Extensions.FileProviders.Embedded
al proyecto.Establezca la propiedad
<GenerateEmbeddedFilesManifest>
entrue
. Especifique los archivos que desea incrustar con<EmbeddedResource>
:<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.0" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="Resource.txt" /> </ItemGroup> </Project>
Use patrones globales para especificar uno o varios archivos para incrustar en el ensamblado.
La aplicación de ejemplo FileProviderSample
crea un ManifestEmbeddedFileProvider
y pasa el ensamblado que se está ejecutando actualmente a su constructor.
Startup.cs
:
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
Las sobrecargas adicionales le permiten:
- Especificar una ruta de acceso de archivo relativa.
- Definir el ámbito de archivos a la fecha de la última modificación.
- Asignar nombre al recurso incrustado que contiene el manifiesto del archivo incrustado.
Sobrecarga | Descripción |
---|---|
ManifestEmbeddedFileProvider(Assembly, String) |
Acepta parámetro de ruta de acceso relativa root opcional. Especifique root para definir el ámbito de las llamadas en GetDirectoryContents en aquellos recursos que se encuentran bajo las rutas de acceso proporcionadas. |
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset) |
Acepta un parámetro de ruta de acceso relativa root opcional y un parámetro de fecha lastModified (DateTimeOffset). La fecha lastModified define el ámbito de la última fecha de modificación para las instancias de IFileInfo que IFileProvider devuelve. |
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset) |
Acepta una ruta de acceso relativa root opcional, una fecha lastModified y parámetros manifestName . manifestName representa el nombre del recurso incrustado que contiene el manifiesto. |
Proveedor de archivos compuestos
CompositeFileProvider combina instancias de IFileProvider
, y expone una única interfaz para trabajar con archivos de varios proveedores. Al crear CompositeFileProvider
, se pasan una o varias instancias de IFileProvider
a su constructor.
En la aplicación de ejemplo FileProviderSample
, un PhysicalFileProvider
y un ManifestEmbeddedFileProvider
proporcionan archivos a un CompositeFileProvider
registrado en el contenedor de servicios de la aplicación. El código siguiente se encuentra en el método Startup.ConfigureServices
del proyecto:
var physicalProvider = _env.ContentRootFileProvider;
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
var compositeProvider =
new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider);
services.AddSingleton<IFileProvider>(compositeProvider);
Observación de cambios
El método IFileProvider.Watch proporciona un escenario para ver uno o más archivos o directorios para detectar cambios. El método Watch
realiza las acciones siguientes:
- Acepta una cadena de ruta de acceso a archivo, que puede usar patrones globales para especificar varios archivos.
- Devuelve un valor IChangeToken.
El token de cambio resultante expone:
- HasChanged: una propiedad que se puede inspeccionar para determinar si se ha producido un cambio.
- RegisterChangeCallback: se llama cuando se detectan cambios en la cadena de ruta de acceso especificada. Cada token de cambio solo llama a su devolución de llamada asociada en respuesta a un único cambio. Para habilitar la supervisión constante, puede usar TaskCompletionSource<TResult> (como se muestra a continuación) o volver a crear instancias de
IChangeToken
en respuesta a los cambios.
La aplicación de ejemplo WatchConsole
escribe un mensaje cada vez que se modifica un archivo .txt
en el directorio TextFiles
:
private static readonly string _fileFilter = Path.Combine("TextFiles", "*.txt");
public static void Main(string[] args)
{
Console.WriteLine($"Monitoring for changes with filter '{_fileFilter}' (Ctrl + C to quit)...");
while (true)
{
MainAsync().GetAwaiter().GetResult();
}
}
private static async Task MainAsync()
{
var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
IChangeToken token = fileProvider.Watch(_fileFilter);
var tcs = new TaskCompletionSource<object>();
token.RegisterChangeCallback(state =>
((TaskCompletionSource<object>)state).TrySetResult(null), tcs);
await tcs.Task.ConfigureAwait(false);
Console.WriteLine("file changed");
}
Algunos sistemas de archivos, como contenedores de Docker y recursos compartidos de red, no pueden enviar notificaciones de cambio de forma confiable. Establezca la variable de entorno DOTNET_USE_POLLING_FILE_WATCHER
en 1
o true
para sondear el sistema de archivos en busca de cambios cada cuatro segundos (no configurable).
Patrones globales
Las rutas de acceso del sistema de archivos utilizan patrones de caracteres comodín denominados patrones globales. Especifique grupos de archivos con estos patrones. Los dos caracteres comodín son *
y **
:
*
Coincide con cualquier elemento del nivel de carpeta actual, con cualquier nombre de archivo o con cualquier extensión de archivo. Las coincidencias finalizan con los caracteres /
y .
en la ruta de acceso de archivo.
**
Coincide con cualquier elemento de varios niveles de directorios. Puede usarse para coincidir de forma recursiva con muchos archivos dentro de una jerarquía de directorios.
En la tabla siguiente se proporcionan ejemplos comunes de patrones globales.
Modelo | Descripción |
---|---|
directory/file.txt |
Coincide con un archivo concreto en un directorio específico. |
directory/*.txt |
Coincide con todos los archivos que tengan la extensión .txt en un directorio específico. |
directory/*/appsettings.json |
Coincide con todos los archivos appsettings.json que estén en directorios exactamente un nivel por debajo de la carpeta directory . |
directory/**/*.txt |
Coincide con todos los archivos con una extensión .txt y que se encuentran en cualquier lugar de la carpeta directory . |
ASP.NET Core abstrae el acceso al sistema de archivos mediante el uso de proveedores de archivos. Los proveedores de archivos se usan en el marco de ASP.NET Core:
- IHostingEnvironment expone la raíz del contenido y la raíz web de la aplicación como tipos
IFileProvider
. - El middleware de archivos estáticos usa proveedores de archivos para buscar archivos estáticos.
- Razor usa proveedores de archivos para localizar páginas y vistas.
- Las herramientas de .NET Core usan proveedores de archivos y patrones globales para especificar los archivos que deben publicarse.
Vea o descargue el código de ejemplo (cómo descargarlo)
Interfaces de proveedor de archivos
La interfaz principal es IFileProvider. IFileProvider
expone métodos para:
- Obtenga la información del archivo (IFileInfo).
- Obtenga la información del directorio (IDirectoryContents).
- Configure las notificaciones de cambio (mediante IChangeToken).
IFileInfo
proporciona métodos y propiedades para trabajar con archivos:
- Exists
- IsDirectory
- Name
- Length (en bytes)
- Fecha LastModified
Puede leer del archivo mediante el método IFileInfo.CreateReadStream.
La aplicación de ejemplo muestra cómo configurar un proveedor de archivos en Startup.ConfigureServices
para su uso en toda la aplicación a través de la inserción de dependencias.
Implementaciones del proveedor de archivos
Hay tres implementaciones de IFileProvider
disponibles.
Implementación | Descripción |
---|---|
PhysicalFileProvider | El proveedor físico se utiliza para acceder a los archivos físicos del sistema. |
ManifestEmbeddedFileProvider | El proveedor insertado de manifiestos se utiliza para tener acceder a archivos insertados en ensamblados. |
CompositeFileProvider | El proveedor compuesto se utiliza para proporcionar acceso combinado a archivos y directorios de uno o más proveedores. |
PhysicalFileProvider
PhysicalFileProvider proporciona acceso al sistema de archivos físico. PhysicalFileProvider
usa el tipo System.IO.File (para el proveedor físico) y define el ámbito de todas las rutas de acceso a un directorio y sus elementos secundarios. Esta definición de ámbito impide el acceso al sistema de archivos fuera del directorio especificado y sus elementos secundarios. El escenario más común para crear y usar PhysicalFileProvider
es solicitar IFileProvider
en un constructor mediante la inyección de dependencias.
Al crear una instancia de este proveedor directamente, se requiere una ruta de acceso del directorio, que actúa como la ruta de acceso base para todas las solicitudes realizadas usando el proveedor.
El código siguiente muestra cómo crear PhysicalFileProvider
y usarlo para obtener el contenido del directorio y la información del archivo:
var provider = new PhysicalFileProvider(applicationRoot);
var contents = provider.GetDirectoryContents(string.Empty);
var fileInfo = provider.GetFileInfo("wwwroot/js/site.js");
Tipos del ejemplo anterior:
provider
esIFileProvider
.contents
esIDirectoryContents
.fileInfo
esIFileInfo
.
El proveedor de archivos puede usarse para iterar por el directorio especificado por applicationRoot
o llamar a GetFileInfo
para obtener información de un archivo. El proveedor de archivos no tiene acceso fuera del directorio applicationRoot
.
La aplicación de ejemplo crea el proveedor en la clase Startup.ConfigureServices
de la aplicación mediante IHostingEnvironment.ContentRootFileProvider:
var physicalProvider = _env.ContentRootFileProvider;
ManifestEmbeddedFileProvider
ManifestEmbeddedFileProvider se utiliza para acceder a archivos insertados dentro de ensamblados. ManifestEmbeddedFileProvider
utiliza un manifiesto compilado en el ensamblado para reconstruir las rutas de acceso originales de los archivos incrustados.
Para generar un manifiesto de los archivos incrustados, establezca la propiedad <GenerateEmbeddedFilesManifest>
en true
. Especifique los archivos que desea incrustar con <EmbeddedResource>:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resource.txt" />
</ItemGroup>
</Project>
Use patrones globales para especificar uno o varios archivos para incrustar en el ensamblado.
La aplicación de ejemplo crea ManifestEmbeddedFileProvider
y pasa el ensamblado que se está ejecutando actualmente a su constructor.
Startup.cs
:
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
Las sobrecargas adicionales le permiten:
- Especificar una ruta de acceso de archivo relativa.
- Definir el ámbito de archivos a la fecha de la última modificación.
- Asignar nombre al recurso incrustado que contiene el manifiesto del archivo incrustado.
Sobrecarga | Descripción |
---|---|
ManifestEmbeddedFileProvider(Assembly, String) |
Acepta parámetro de ruta de acceso relativa root opcional. Especifique root para definir el ámbito de las llamadas en GetDirectoryContents en aquellos recursos que se encuentran bajo las rutas de acceso proporcionadas. |
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset) |
Acepta un parámetro de ruta de acceso relativa root opcional y un parámetro de fecha lastModified (DateTimeOffset). La fecha lastModified define el ámbito de la última fecha de modificación para las instancias de IFileInfo que IFileProvider devuelve. |
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset) |
Acepta una ruta de acceso relativa root opcional, una fecha lastModified y parámetros manifestName . manifestName representa el nombre del recurso incrustado que contiene el manifiesto. |
CompositeFileProvider
CompositeFileProvider combina instancias de IFileProvider
, y expone una única interfaz para trabajar con archivos de varios proveedores. Al crear CompositeFileProvider
, se pasan una o varias instancias de IFileProvider
a su constructor.
En la aplicación de ejemplo, PhysicalFileProvider
y ManifestEmbeddedFileProvider
proporcionan archivos a un CompositeFileProvider
registrado en el contenedor de servicios de la aplicación:
var physicalProvider = _env.ContentRootFileProvider;
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
var compositeProvider =
new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider);
services.AddSingleton<IFileProvider>(compositeProvider);
Observación de cambios
El método IFileProvider.Watch proporciona un escenario para ver uno o más archivos o directorios para detectar cambios. Watch
acepta una cadena de ruta de acceso, que puede usar patrones globales para especificar varios archivos. Watch
devuelve un valor de IChangeToken. El token de cambio expone:
- HasChanged: una propiedad que se puede inspeccionar para determinar si se ha producido un cambio.
- RegisterChangeCallback: se llama cuando se detectan cambios en la cadena de ruta de acceso especificada. Cada token de cambio solo llama a su devolución de llamada asociada en respuesta a un único cambio. Para habilitar la supervisión constante, puede usar TaskCompletionSource<TResult> (como se muestra a continuación) o volver a crear instancias de
IChangeToken
en respuesta a los cambios.
En la aplicación de ejemplo, la aplicación de consola WatchConsole se configura para mostrar un mensaje cada vez que se modifica un archivo de texto:
private static PhysicalFileProvider _fileProvider =
new PhysicalFileProvider(Directory.GetCurrentDirectory());
public static void Main(string[] args)
{
Console.WriteLine("Monitoring quotes.txt for changes (Ctrl-c to quit)...");
while (true)
{
MainAsync().GetAwaiter().GetResult();
}
}
private static async Task MainAsync()
{
IChangeToken token = _fileProvider.Watch("quotes.txt");
var tcs = new TaskCompletionSource<object>();
token.RegisterChangeCallback(state =>
((TaskCompletionSource<object>)state).TrySetResult(null), tcs);
await tcs.Task.ConfigureAwait(false);
Console.WriteLine("quotes.txt changed");
}
Algunos sistemas de archivos, como contenedores de Docker y recursos compartidos de red, no pueden enviar notificaciones de cambio de forma confiable. Establezca la variable de entorno DOTNET_USE_POLLING_FILE_WATCHER
en 1
o true
para sondear el sistema de archivos en busca de cambios cada cuatro segundos (no configurable).
Patrones globales
Las rutas de acceso del sistema de archivos utilizan patrones de caracteres comodín denominados patrones globales. Especifique grupos de archivos con estos patrones. Los dos caracteres comodín son *
y **
:
*
Coincide con cualquier elemento del nivel de carpeta actual, con cualquier nombre de archivo o con cualquier extensión de archivo. Las coincidencias finalizan con los caracteres /
y .
en la ruta de acceso de archivo.
**
Coincide con cualquier elemento de varios niveles de directorios. Puede usarse para coincidir de forma recursiva con muchos archivos dentro de una jerarquía de directorios.
Ejemplos de patrones globales
directory/file.txt
Coincide con un archivo concreto en un directorio específico.
directory/*.txt
Coincide con todos los archivos que tengan la extensión .txt en un directorio específico.
directory/*/appsettings.json
Coincide con todos los archivos appsettings.json
que estén en directorios exactamente un nivel por debajo de la carpeta directorio.
directory/**/*.txt
Coincide con todos los archivos que tengan la extensión .txt y se encuentren en cualquier lugar de la carpeta directorio.