Поставщики файлов в ASP.NET Core
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 9 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске см . версию .NET 9 этой статьи.
Автор: Стив Смит (Steve Smith)
ASP.NET Core абстрагирует доступ к файловой системе с помощью поставщиков файлов. В рамках платформы ASP.NET Core используются поставщики файлов. Например:
- IWebHostEnvironment предоставляет корневой каталог содержимого и корневой каталог документов приложения в виде типов
IFileProvider
. - ПО промежуточного слоя для статических файлов использует поставщики файлов для поиска статических файлов.
- Razor использует поставщики файлов для поиска страниц и представлений.
- Инструменты .NET Core используют поставщики файлов и стандартные маски, чтобы указать файлы для публикации.
Просмотреть или скачать образец кода (описание загрузки)
Интерфейсы поставщика файлов
Основной интерфейс — IFileProvider. IFileProvider
предоставляет методы для следующих действий:
- получение сведений о файле (IFileInfo);
- получение сведений о каталоге (IDirectoryContents);
- настройка уведомлений об изменениях (с помощью IChangeToken).
IFileInfo
предоставляет методы и свойства для работы с файлами:
- Exists
- IsDirectory
- Name
- Length (в байтах);
- LastModified (дата).
Считывать данные из файла можно с помощью метода IFileInfo.CreateReadStream.
Пример приложения FileProviderSample
демонстрирует, как настроить поставщик файлов в Startup.ConfigureServices
, чтобы использовать его в приложении путем внедрения зависимостей.
Реализации поставщиков файлов
В следующей таблице перечислены реализации IFileProvider
.
Внедрение | Description |
---|---|
Составной поставщик файлов | Используется для предоставления комбинированного доступа к файлам и каталогам из одного или нескольких поставщиков. |
Поставщик внедренных файлов манифестов | Используется для доступа к файлам, внедренным в сборки. |
Поставщик физических файлов | Используется для доступа к физическим файлам системы. |
Поставщик физических файлов
PhysicalFileProvider предоставляет доступ к физической файловой системе. PhysicalFileProvider
использует тип System.IO.File (для физического поставщика), ограничивая все пути каталогом и его дочерними элементами. Такая привязка к области защищает от доступа к файловой системе за пределами указанного каталога и его дочерних элементов. Самый распространенный подход к созданию и использованию PhysicalFileProvider
— запросить IFileProvider
в конструкторе путем внедрения зависимостей.
При непосредственном создании экземпляра этого поставщика нужно указать абсолютный путь к каталогу, который станет базовым путем для всех запросов, выполненных с помощью этого поставщика. Стандартные маски не поддерживаются в пути к каталогу.
Следующий код демонстрирует, как использовать PhysicalFileProvider
для получения содержимого каталога и сведений о файлах:
var provider = new PhysicalFileProvider(applicationRoot);
var contents = provider.GetDirectoryContents(string.Empty);
var filePath = Path.Combine("wwwroot", "js", "site.js");
var fileInfo = provider.GetFileInfo(filePath);
В предшествующем примере используются следующие типы:
- Аргумент
provider
имеет типIFileProvider
. - Аргумент
contents
имеет типIDirectoryContents
. - Аргумент
fileInfo
имеет типIFileInfo
.
С помощью поставщика файлов вы можете выполнить итерацию по каталогу, указанному в параметре applicationRoot
, или вызвать GetFileInfo
для получения сведений о файлах. Стандартные маски невозможно передать методу GetFileInfo
. Поставщик файлов не имеет доступ к каталогам за пределами applicationRoot
.
Пример FileProviderSample
приложения создает поставщика в методе Startup.ConfigureServices
с помощью IHostEnvironment.ContentRootFileProvider:
var physicalProvider = _env.ContentRootFileProvider;
Поставщик внедренных файлов манифестов
ManifestEmbeddedFileProvider используется для доступа к файлам, внедренным в сборки. ManifestEmbeddedFileProvider
использует манифест, скомпилированный в сборку, для воссоздания исходных путей для внедренных файлов.
Чтобы создать манифест для внедренных файлов, сделайте следующее:
Добавьте в проект пакет NuGet
Microsoft.Extensions.FileProviders.Embedded
.Установите свойство
<GenerateEmbeddedFilesManifest>
в значениеtrue
. Укажите файлы для внедрения с<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>
Используйте стандартные маски для указания одного или нескольких файлов, которые вы хотите внедрить в сборку.
Наш пример приложения FileProviderSample
создает ManifestEmbeddedFileProvider
и передает текущую выполняемую сборку в соответствующий конструктор.
Startup.cs
:
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
Дополнительные перегрузки позволяют сделать следующее:
- указать относительный путь к файлу;
- ограничить файлы по дате последнего изменения;
- указать имя внедренного ресурса, содержащего внедренный файл манифеста.
Перегрузка | Description |
---|---|
ManifestEmbeddedFileProvider(Assembly, String) |
Принимает необязательный параметр root со значением относительного пути. Укажите root , чтобы ограничить вызовы к GetDirectoryContents только ресурсами по указанному пути. |
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset) |
Принимает необязательный параметр root со значением относительного пути и параметр lastModified со значением даты (DateTimeOffset). Параметр lastModified ограничивает дату последнего изменения для экземпляров IFileInfo, возвращаемых функцией IFileProvider. |
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset) |
Принимает необязательный параметр root со значением относительного пути, дату lastModified и параметры manifestName . manifestName здесь представляет имя встроенного ресурса, содержащего манифест. |
Составной поставщик файлов
CompositeFileProvider объединяет экземпляры IFileProvider
, предоставляя единый интерфейс для работы с файлами от нескольких поставщиков. При создании CompositeFileProvider
передайте в соответствующий конструктор один или несколько экземпляров IFileProvider
:
В нашем примере приложения FileProviderSample
поставщики PhysicalFileProvider
и ManifestEmbeddedFileProvider
предоставляют файлы для CompositeFileProvider
с регистрацией в контейнере служб приложения. Следующий код находится в методе Startup.ConfigureServices
проекта:
var physicalProvider = _env.ContentRootFileProvider;
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
var compositeProvider =
new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider);
services.AddSingleton<IFileProvider>(compositeProvider);
Отслеживание изменений
Метод IFileProvider.Watch позволяет просматривать один или несколько файлов или каталогов на предмет изменений. Метод Watch
:
- Принимает строку пути, которая может использовать стандартные маски для указания нескольких файлов.
- Возвращает значение типа IChangeToken.
Итоговый токен изменений предоставляет следующие свойства:
- HasChanged: свойство, которое можно проверить, чтобы определить, произошло ли изменение.
- RegisterChangeCallback: вызывается при обнаружении изменений в указанной строке пути. Каждый токен изменения выполняет соответствующий обратный вызов только в ответ на отдельное изменение. Чтобы реализовать непрерывный мониторинг, используйте TaskCompletionSource<TResult>, как показано ниже, или повторно создавайте экземпляры
IChangeToken
в ответ на изменения.
Пример WatchConsole
приложения записывает сообщение при изменении .txt
файла в каталоге 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");
}
Некоторые файловые системы, такие как контейнеры Docker и сетевые папки, не могут надежно отправлять уведомления об изменениях. Задайте для переменной среды DOTNET_USE_POLLING_FILE_WATCHER
значение 1
или true
, чтобы опрашивать файловую систему на предмет изменений каждые 4 секунды (это значение нельзя изменить).
Стандартные маски
В путях файловой системы используются шаблоны подстановочных знаков, которые называются стандартными масками. Эти маски позволяют указывать группы файлов. Поддерживаются два подстановочных знака — *
и **
.
*
Совпадает с любым элементом на текущем уровне папок, любым именем или расширением файла. Совпадения завершаются символами /
и .
в пути файла.
**
Совпадает со всем содержимым на разных уровнях каталогов. Может использоваться для рекурсивного сопоставления множества файлов в иерархии каталогов.
Следующая таблица содержит типичные примеры стандартных масок.
Расписание | Description |
---|---|
directory/file.txt |
Соответствует конкретному файлу в заданном каталоге. |
directory/*.txt |
Соответствует всем файлам с расширением .txt в заданном каталоге. |
directory/*/appsettings.json |
Соответствует всем appsettings.json файлам в каталогах ровно один уровень ниже directory папки. |
directory/**/*.txt |
Соответствует всем файлам с расширением, найденным .txt в любом месте в папке directory . |
ASP.NET Core абстрагирует доступ к файловой системе с помощью поставщиков файлов. В рамках платформы ASP.NET Core используются поставщики файлов.
- IHostingEnvironment предоставляет корневой каталог содержимого и корневой каталог документов приложения в виде типов
IFileProvider
. - ПО промежуточного слоя для статических файлов использует поставщики файлов для поиска статических файлов.
- Razor использует поставщики файлов для поиска страниц и представлений.
- Инструменты .NET Core используют поставщики файлов и стандартные маски, чтобы указать файлы для публикации.
Просмотреть или скачать образец кода (описание загрузки)
Интерфейсы поставщика файлов
Основной интерфейс — IFileProvider. IFileProvider
предоставляет методы для следующих действий:
- получение сведений о файле (IFileInfo);
- получение сведений о каталоге (IDirectoryContents);
- настройка уведомлений об изменениях (с помощью IChangeToken).
IFileInfo
предоставляет методы и свойства для работы с файлами:
- Exists
- IsDirectory
- Name
- Length (в байтах);
- LastModified (дата).
Данные из файла можно считывать с помощью метода IFileInfo.CreateReadStream.
Пример приложения демонстрирует, как настроить в Startup.ConfigureServices
поставщике файлов, чтобы использовать его в приложении путем внедрения зависимостей.
Реализации поставщиков файлов
Доступны три реализации IFileProvider
.
Внедрение | Description |
---|---|
PhysicalFileProvider | Физический поставщик используется для доступа к физическим файлам системы. |
ManifestEmbeddedFileProvider | Поставщик внедренных манифестов используется для доступа к файлам, внедренным в сборки. |
CompositeFileProvider | Составной поставщик используется для предоставления комбинированного доступа к файлам и каталогам из одного или нескольких поставщиков. |
PhysicalFileProvider
PhysicalFileProvider предоставляет доступ к физической файловой системе. PhysicalFileProvider
использует тип System.IO.File (для физического поставщика), ограничивая все пути каталогом и его дочерними элементами. Такая привязка к области защищает от доступа к файловой системе за пределами указанного каталога и его дочерних элементов. Самый распространенный подход к созданию и использованию PhysicalFileProvider
— запросить IFileProvider
в конструкторе путем внедрения зависимостей.
При непосредственном создании экземпляра этого поставщика нужно указать путь к каталогу, который станет базовым путем для всех запросов, выполненных с помощью этого поставщика.
Следующий пример кода демонстрирует, как создать и использовать PhysicalFileProvider
для получения содержимого каталога и сведений о файлах:
var provider = new PhysicalFileProvider(applicationRoot);
var contents = provider.GetDirectoryContents(string.Empty);
var fileInfo = provider.GetFileInfo("wwwroot/js/site.js");
В предшествующем примере используются следующие типы:
- Аргумент
provider
имеет типIFileProvider
. - Аргумент
contents
имеет типIDirectoryContents
. - Аргумент
fileInfo
имеет типIFileInfo
.
С помощью поставщика файлов вы можете выполнить итерацию по каталогу, указанному в параметре applicationRoot
, или вызвать GetFileInfo
для получения сведений о файлах. Поставщик файлов не имеет доступ к каталогам за пределами applicationRoot
.
Этот пример приложения создает поставщик для приложения в классе Startup.ConfigureServices
, используя IHostingEnvironment.ContentRootFileProvider:
var physicalProvider = _env.ContentRootFileProvider;
ManifestEmbeddedFileProvider
ManifestEmbeddedFileProvider используется для доступа к файлам, внедренным в сборки. ManifestEmbeddedFileProvider
использует манифест, скомпилированный в сборку, для воссоздания исходных путей для внедренных файлов.
Чтобы создать манифест для внедренных файлов, задайте для свойства <GenerateEmbeddedFilesManifest>
значение true
. Выберите файлы для внедрения с помощью <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>
Используйте стандартные маски для указания одного или нескольких файлов, которые вы хотите внедрить в сборку.
Наш пример приложения создает ManifestEmbeddedFileProvider
и передает в соответствующий конструктор текущую выполняемую сборку.
Startup.cs
:
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
Дополнительные перегрузки позволяют сделать следующее:
- указать относительный путь к файлу;
- ограничить файлы по дате последнего изменения;
- указать имя внедренного ресурса, содержащего внедренный файл манифеста.
Перегрузка | Description |
---|---|
ManifestEmbeddedFileProvider(Assembly, String) |
Принимает необязательный параметр root со значением относительного пути. Укажите root , чтобы ограничить вызовы к GetDirectoryContents только ресурсами по указанному пути. |
ManifestEmbeddedFileProvider(Assembly, String, DateTimeOffset) |
Принимает необязательный параметр root со значением относительного пути и параметр lastModified со значением даты (DateTimeOffset). Параметр lastModified ограничивает дату последнего изменения для экземпляров IFileInfo, возвращаемых функцией IFileProvider. |
ManifestEmbeddedFileProvider(Assembly, String, String, DateTimeOffset) |
Принимает необязательный параметр root со значением относительного пути, дату lastModified и параметры manifestName . manifestName здесь представляет имя встроенного ресурса, содержащего манифест. |
CompositeFileProvider
CompositeFileProvider объединяет экземпляры IFileProvider
, предоставляя единый интерфейс для работы с файлами от нескольких поставщиков. При создании CompositeFileProvider
передайте в соответствующий конструктор один или несколько экземпляров IFileProvider
:
В нашем примере приложения PhysicalFileProvider
и ManifestEmbeddedFileProvider
предоставляют файлы для CompositeFileProvider
с регистрацией в контейнере служб приложения:
var physicalProvider = _env.ContentRootFileProvider;
var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(typeof(Program).Assembly);
var compositeProvider =
new CompositeFileProvider(physicalProvider, manifestEmbeddedProvider);
services.AddSingleton<IFileProvider>(compositeProvider);
Отслеживание изменений
Метод IFileProvider.Watch позволяет контролировать изменения в одном или нескольких файлах или каталогах. Watch
принимает строку пути, которая можно использовать стандартные маски для указания нескольких файлов. Watch
возвращает IChangeToken. Этот токен изменений предоставляет следующие свойства:
- HasChanged: свойство, которое можно проверить, чтобы определить, произошло ли изменение.
- RegisterChangeCallback: вызывается при обнаружении изменений в указанной строке пути. Каждый токен изменения выполняет соответствующий обратный вызов только в ответ на отдельное изменение. Чтобы реализовать непрерывный мониторинг, используйте TaskCompletionSource<TResult>, как показано ниже, или повторно создавайте экземпляры
IChangeToken
в ответ на изменения.
В нашем примере консольное приложение WatchConsole будет отображать сообщение при изменении текстового файла:
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");
}
Некоторые файловые системы, такие как контейнеры Docker и сетевые папки, не могут надежно отправлять уведомления об изменениях. Задайте для переменной среды DOTNET_USE_POLLING_FILE_WATCHER
значение 1
или true
, чтобы опрашивать файловую систему на предмет изменений каждые 4 секунды (это значение нельзя изменить).
Стандартные маски
В путях файловой системы используются шаблоны подстановочных знаков, которые называются стандартными масками. Эти маски позволяют указывать группы файлов. Поддерживаются два подстановочных знака — *
и **
.
*
Совпадает с любым элементом на текущем уровне папок, любым именем или расширением файла. Совпадения завершаются символами /
и .
в пути файла.
**
Совпадает со всем содержимым на разных уровнях каталогов. Может использоваться для рекурсивного сопоставления множества файлов в иерархии каталогов.
Примеры стандартных масок
directory/file.txt
Соответствует конкретному файлу в заданном каталоге.
directory/*.txt
Соответствует всем файлам с расширением .txt в заданном каталоге.
directory/*/appsettings.json
Соответствует всем файлам appsettings.json
в любом каталоге, расположенном ровно на один уровень ниже папки directory.
directory/**/*.txt
Соответствует всем файлам с расширением .txt, находящимся на любом уровне ниже каталога directory.
ASP.NET Core