Provedores de arquivos no ASP.NET Core
Observação
Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Importante
Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.
Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Por Steve Smith
O ASP.NET Core abstrai o acesso ao sistema de arquivos por meio do uso de provedores de arquivos. Os provedores de arquivos são usados em toda a estrutura do ASP.NET Core. Por exemplo:
- IWebHostEnvironment expõe a raiz de conteúdo do aplicativo e a raiz da Web como tipos
IFileProvider
. - O middleware de arquivos estáticos usa provedores de arquivos para localizar arquivos estáticos.
- Razor usa provedores de arquivos para localizar páginas e modos de exibição.
- As ferramentas do .NET Core usam provedores de arquivos e padrões glob para especificar quais arquivos devem ser publicados.
Exibir ou baixar código de exemplo (como baixar)
Interfaces de provedor de arquivo
A interface principal é IFileProvider. IFileProvider
expõe métodos para:
- Obter informações do arquivo (IFileInfo).
- Obter informações do diretório (IDirectoryContents).
- Configurar notificações de alteração (usando um IChangeToken).
IFileInfo
fornece métodos e propriedades para trabalhar com arquivos:
- Exists
- IsDirectory
- Name
- Length (em bytes)
- Data de LastModified
É possível ler do arquivo usando o método IFileInfo.CreateReadStream.
O aplicativo de amostra FileProviderSample
demonstra como configurar um provedor de arquivos em Startup.ConfigureServices
para uso em todo o aplicativo por meio da injeção de dependência.
Implementações do provedor de arquivos
A tabela a seguir lista as implementações de IFileProvider
.
Implementação | Descrição |
---|---|
Provedor de arquivos compostos | Usado para fornecer acesso combinado a arquivos e diretórios de um ou mais provedores. |
Provedor de arquivos inseridos de manifesto | Usado para acessar arquivos inseridos em assemblies. |
Provedor de arquivos físicos | Usado para acessar os arquivos físicos do sistema. |
Provedor de arquivos físicos
O PhysicalFileProvider fornece acesso ao sistema de arquivos físico. O PhysicalFileProvider
usa o tipo System.IO.File (para o provedor físico) e define o escopo de todos os caminhos para um diretório e seus filhos. Esse escopo impede o acesso ao sistema de arquivos fora do diretório especificado e seus filhos. O cenário mais comum para criar e usar um PhysicalFileProvider
é solicitar um IFileProvider
em um construtor por meio de injeção de dependência.
Ao criar uma instância para esse provedor, um caminho de diretório absoluto é necessário e serve como o caminho base para todas as solicitações feitas usando o provedor. Não há suporte para padrões glob no caminho do diretório.
O código a seguir mostra como usar PhysicalFileProvider
para obter o conteúdo do diretório e as informações do arquivo:
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 no exemplo anterior:
provider
é umIFileProvider
.contents
é umIDirectoryContents
.fileInfo
é umIFileInfo
.
O provedor de arquivos pode ser usado para percorrer o diretório especificado por applicationRoot
ou chamar GetFileInfo
para obter as informações de um arquivo. Padrões glob não podem ser passados para o método GetFileInfo
. O provedor de arquivos não tem acesso fora do diretório applicationRoot
.
O aplicativo de exemplo FileProviderSample
cria o provedor no método Startup.ConfigureServices
usando IHostEnvironment.ContentRootFileProvider:
var physicalProvider = _env.ContentRootFileProvider;
Provedor de arquivos inseridos de manifesto
O ManifestEmbeddedFileProvider é usado para acessar arquivos inseridos em assemblies. O ManifestEmbeddedFileProvider
usa um manifesto compilado no assembly para reconstruir os caminhos originais dos arquivos inseridos.
Para gerar um manifesto dos arquivos inseridos:
Adicione o pacote NuGet
Microsoft.Extensions.FileProviders.Embedded
ao seu projeto.Defina a propriedade
<GenerateEmbeddedFilesManifest>
comotrue
. Especifique os arquivos a serem inseridos com<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 padrões glob para especificar um ou mais arquivos a serem inseridos no assembly.
O aplicativo de amostra FileProviderSample
cria um ManifestEmbeddedFileProvider
e passa o assembly atualmente em execução para seu construtor.
Startup.cs
:
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
Sobrecargas adicionais permitem:
- Especificar um caminho de arquivo relativo.
- Delimitar os arquivos segundo a data da última modificação.
- Nomear o recurso inserido que contém o manifesto do arquivo inserido.
Sobrecarga | Descrição |
---|---|
ManifestEmbeddedFileProvider(Assembly, String) |
Aceita um parâmetro de caminho relativo root opcional. Especifique o root para definir o escopo das chamadas de GetDirectoryContents para esses recursos no caminho fornecido. |
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset) |
Aceita um parâmetro de caminho relativo root opcional e um parâmetro de data lastModified (DateTimeOffset). A data lastModified tem como escopo a data da última modificação das instâncias de IFileInfo retornadas por IFileProvider. |
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset) |
Aceita um caminho relativo root opcional, data de lastModified e parâmetros manifestName . O manifestName representa o nome do recurso inserido que contém o manifesto. |
Provedor de arquivos compostos
O CompositeFileProvider combina instâncias de IFileProvider
, expondo uma interface única para trabalhar com arquivos de vários provedores. Ao criar o CompositeFileProvider
, passe uma ou mais instâncias de IFileProvider
para o construtor.
No aplicativo de amostra FileProviderSample
, um PhysicalFileProvider
e um ManifestEmbeddedFileProvider
fornecem arquivos para um CompositeFileProvider
registrado no contêiner de serviço do aplicativo. O código a seguir é encontrado no método Startup.ConfigureServices
do projeto:
var physicalProvider = _env.ContentRootFileProvider;
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
var compositeProvider =
new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider);
services.AddSingleton<IFileProvider>(compositeProvider);
Monitorar as alterações
O método IFileProvider.Watch proporciona um cenário para monitorar um ou mais arquivos ou diretórios quanto a alterações. O método Watch
:
- Aceita uma cadeia de caracteres de caminho de arquivo, que pode usar padrões glob para especificar vários arquivos.
- Retorna um IChangeToken.
O token de alteração resultante expõe:
- HasChanged: uma propriedade que pode ser inspecionada para determinar se uma alteração ocorreu.
- RegisterChangeCallback: chamada quando são detectadas alterações na cadeia de caracteres do caminho especificado. Cada token de alteração chama apenas seu retorno de chamada associado em resposta a uma única alteração. Para permitir o monitoramento constante, use um TaskCompletionSource<TResult> (mostrado abaixo) ou recrie instâncias de
IChangeToken
em resposta a alterações.
O aplicativo de exemplo WatchConsole
grava uma mensagem sempre que um arquivo .txt
no diretório TextFiles
é modificado:
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");
}
Alguns sistemas de arquivos, como contêineres do Docker e compartilhamentos de rede, podem não enviar notificações de alteração de forma confiável. Defina a variável de ambiente DOTNET_USE_POLLING_FILE_WATCHER
como 1
ou true
para sondar o sistema de arquivos a cada quatro segundos em relação a alterações.
Padrões glob
Os caminhos do sistema de arquivos usam padrões curinga chamados padrões glob (ou globbing). Especifique grupos de arquivos com esses padrões. Os dois caracteres curinga são *
e **
:
*
Corresponde a qualquer coisa no nível da pasta atual, qualquer nome de arquivo ou qualquer extensão de arquivo. As correspondências são terminadas pelos caracteres /
e .
no caminho do arquivo.
**
Coincide a qualquer coisa em vários níveis de diretório. Pode ser usada para fazer a correspondência recursiva com vários arquivos em uma hierarquia de diretórios.
A tabela a seguir fornece exemplos comuns de padrões glob.
Padrão | Descrição |
---|---|
directory/file.txt |
Corresponde a um arquivo específico em um diretório específico. |
directory/*.txt |
Corresponde a todos os arquivos com a extensão .txt em um diretório específico. |
directory/*/appsettings.json |
Corresponde a todos os arquivos appsettings.json em diretórios que estão exatamente um nível abaixo da pasta directory . |
directory/**/*.txt |
Corresponde a todos os arquivos com a extensão .txt encontrados em qualquer lugar abaixo da pasta directory . |
O ASP.NET Core abstrai o acesso ao sistema de arquivos por meio do uso de provedores de arquivos. Os provedores de arquivos são usados em toda a estrutura do ASP.NET Core:
- IHostingEnvironment expõe a raiz de conteúdo do aplicativo e a raiz da Web como tipos
IFileProvider
. - O middleware de arquivos estáticos usa provedores de arquivos para localizar arquivos estáticos.
- Razor usa provedores de arquivos para localizar páginas e modos de exibição.
- As ferramentas do .NET Core usam provedores de arquivos e padrões glob para especificar quais arquivos devem ser publicados.
Exibir ou baixar código de exemplo (como baixar)
Interfaces de provedor de arquivo
A interface principal é IFileProvider. IFileProvider
expõe métodos para:
- Obter informações do arquivo (IFileInfo).
- Obter informações do diretório (IDirectoryContents).
- Configurar notificações de alteração (usando um IChangeToken).
IFileInfo
fornece métodos e propriedades para trabalhar com arquivos:
- Exists
- IsDirectory
- Name
- Length (em bytes)
- Data de LastModified
Você pode ler o arquivo usando o método IFileInfo.CreateReadStream.
O aplicativo de amostra demonstra como configurar um provedor de arquivos em Startup.ConfigureServices
para uso em todo o aplicativo por meio da injeção de dependência.
Implementações do provedor de arquivos
Três implementações de IFileProvider
estão disponíveis.
Implementação | Descrição |
---|---|
PhysicalFileProvider | O provedor físico é usado para acessar os arquivos físicos do sistema. |
ManifestEmbeddedFileProvider | O provedor inserido de manifesto é usado para acessar arquivos incorporados em assemblies. |
CompositeFileProvider | O provedor composto é usado para fornecer acesso combinado a arquivos e diretórios de um ou mais provedores. |
PhysicalFileProvider
O PhysicalFileProvider fornece acesso ao sistema de arquivos físico. O PhysicalFileProvider
usa o tipo System.IO.File (para o provedor físico) e define o escopo de todos os caminhos para um diretório e seus filhos. Esse escopo impede o acesso ao sistema de arquivos fora do diretório especificado e seus filhos. O cenário mais comum para criar e usar um PhysicalFileProvider
é solicitar um IFileProvider
em um construtor por meio de injeção de dependência.
Ao criar uma instância para esse provedor, um caminho de diretório é necessário e serve como o caminho base para todas as solicitações feitas usando o provedor.
O código a seguir mostra como criar um PhysicalFileProvider
e usá-lo para obter o conteúdo do diretório e as informações do arquivo:
var provider = new PhysicalFileProvider(applicationRoot);
var contents = provider.GetDirectoryContents(string.Empty);
var fileInfo = provider.GetFileInfo("wwwroot/js/site.js");
Tipos no exemplo anterior:
provider
é umIFileProvider
.contents
é umIDirectoryContents
.fileInfo
é umIFileInfo
.
O provedor de arquivos pode ser usado para percorrer o diretório especificado por applicationRoot
ou chamar GetFileInfo
para obter as informações de um arquivo. O provedor de arquivos não tem acesso fora do diretório applicationRoot
.
O aplicativo de amostra cria o provedor na classe Startup.ConfigureServices
do aplicativo usando IHostingEnvironment.ContentRootFileProvider:
var physicalProvider = _env.ContentRootFileProvider;
ManifestEmbeddedFileProvider
O ManifestEmbeddedFileProvider é usado para acessar arquivos inseridos em assemblies. O ManifestEmbeddedFileProvider
usa um manifesto compilado no assembly para reconstruir os caminhos originais dos arquivos inseridos.
Para gerar um manifesto dos arquivos inseridos, defina a propriedade <GenerateEmbeddedFilesManifest>
como true
. Especifique os arquivos para inserir com <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 padrões glob para especificar um ou mais arquivos a serem inseridos no assembly.
O aplicativo de amostra cria um ManifestEmbeddedFileProvider
e passa o assembly atualmente em execução para seu construtor.
Startup.cs
:
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
Sobrecargas adicionais permitem:
- Especificar um caminho de arquivo relativo.
- Delimitar os arquivos segundo a data da última modificação.
- Nomear o recurso inserido que contém o manifesto do arquivo inserido.
Sobrecarga | Descrição |
---|---|
ManifestEmbeddedFileProvider(Assembly, String) |
Aceita um parâmetro de caminho relativo root opcional. Especifique o root para definir o escopo das chamadas de GetDirectoryContents para esses recursos no caminho fornecido. |
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset) |
Aceita um parâmetro de caminho relativo root opcional e um parâmetro de data lastModified (DateTimeOffset). A data lastModified tem como escopo a data da última modificação das instâncias de IFileInfo retornadas por IFileProvider. |
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset) |
Aceita um caminho relativo root opcional, data de lastModified e parâmetros manifestName . O manifestName representa o nome do recurso inserido que contém o manifesto. |
CompositeFileProvider
O CompositeFileProvider combina instâncias de IFileProvider
, expondo uma interface única para trabalhar com arquivos de vários provedores. Ao criar o CompositeFileProvider
, passe uma ou mais instâncias de IFileProvider
para o construtor.
No aplicativo de amostra, um PhysicalFileProvider
e um ManifestEmbeddedFileProvider
fornecem arquivos para um CompositeFileProvider
registrado no contêiner de serviço do aplicativo:
var physicalProvider = _env.ContentRootFileProvider;
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
var compositeProvider =
new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider);
services.AddSingleton<IFileProvider>(compositeProvider);
Monitorar as alterações
O método IFileProvider.Watch proporciona um cenário para monitorar um ou mais arquivos ou diretórios quanto a alterações. Watch
aceita uma cadeia de caracteres de caminho, que pode usar padrões glob para especificar vários arquivos. Watch
retorna um IChangeToken. O token de alteração expõe:
- HasChanged: uma propriedade que pode ser inspecionada para determinar se uma alteração ocorreu.
- RegisterChangeCallback: chamada quando são detectadas alterações na cadeia de caracteres do caminho especificado. Cada token de alteração chama apenas seu retorno de chamada associado em resposta a uma única alteração. Para permitir o monitoramento constante, use um TaskCompletionSource<TResult> (mostrado abaixo) ou recrie instâncias de
IChangeToken
em resposta a alterações.
No aplicativo de amostra, o aplicativo de console WatchConsole é configurado para exibir uma mensagem sempre que um arquivo de texto é modificado:
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");
}
Alguns sistemas de arquivos, como contêineres do Docker e compartilhamentos de rede, podem não enviar notificações de alteração de forma confiável. Defina a variável de ambiente DOTNET_USE_POLLING_FILE_WATCHER
como 1
ou true
para sondar o sistema de arquivos a cada quatro segundos em relação a alterações.
Padrões glob
Os caminhos do sistema de arquivos usam padrões curinga chamados padrões glob (ou globbing). Especifique grupos de arquivos com esses padrões. Os dois caracteres curinga são *
e **
:
*
Corresponde a qualquer coisa no nível da pasta atual, qualquer nome de arquivo ou qualquer extensão de arquivo. As correspondências são terminadas pelos caracteres /
e .
no caminho do arquivo.
**
Coincide a qualquer coisa em vários níveis de diretório. Pode ser usada para fazer a correspondência recursiva com vários arquivos em uma hierarquia de diretórios.
Exemplos de padrão glob
directory/file.txt
Corresponde a um arquivo específico em um diretório específico.
directory/*.txt
Corresponde a todos os arquivos com a extensão .txt em um diretório específico.
directory/*/appsettings.json
Corresponde a todos os arquivos appsettings.json
em diretórios que estão exatamente um nível abaixo da pasta diretório.
directory/**/*.txt
Corresponde a todos os arquivos com a extensão .txt encontrados em qualquer lugar abaixo da pasta diretório.