- ASP.NET Core abstracts file system access through the use of File Providers.
- File Providers are an abstraction over file systems.
- The main interface is
IFileProvider
. IFileProvider
exposes methods to get file information (IFileInfo
), directory information (IDirectoryContents
), and to set up change notifications (using an IChangeToken
).
IFileInfo
provides methods and properties about individual files or directories.
- It has two boolean properties,
Exists
and IsDirectory
, as well as properties describing the file's Name
, Length
(in bytes), and LastModified
date.
- You can read from the file using its
CreateReadStream
method.
- Three implementations of
IFileProvider
are available: Physical, Embedded, and Composite.
- The physical provider is used to access the actual system's files.
- The embedded provider is used to access files embedded in assemblies.
- The composite provider is used to provide combined access to files and directories from one or more other providers.
PhysicalFileProvider
- The
PhysicalFileProvider
provides access to the physical file system. It wraps the System.IO.File
type (for the physical provider), scoping all paths to a directory and its children.
- This scoping limits access to a certain directory and its children, preventing access to the file system outside of this boundary.
- When instantiating this provider, you must provide it with a directory path, which serves as the base path for all requests made to this provider (and which restricts access outside of this path).
- In an ASP.NET Core app, you can instantiate a
PhysicalFileProvider
provider directly, or you can request an IFileProvider
in a Controller or service's constructor through dependency injection.
IFileProvider provider = new PhysicalFileProvider(applicationRoot);
IDirectoryContents contents = provider.GetDirectoryContents(""); // the applicationRoot contents
IFileInfo fileInfo = provider.GetFileInfo("wwwroot/js/site.js"); // a file under applicationRoot
- You can iterate through its directory contents or get a specific file's information by providing a subpath.
- To request a provider from a controller, specify it in the controller's constructor and assign it to a local field.
- Use the local instance from your action methods:
public class HomeController : Controller
{
private readonly IFileProvider _fileProvider;
public HomeController(IFileProvider fileProvider)
{
_fileProvider = fileProvider;
}
public IActionResult Index()
{
var contents = _fileProvider.GetDirectoryContents("");
return View(contents);
}
- Then, create the provider in the app's
Startup
class:
public class Startup
{
private IHostingEnvironment _hostingEnvironment;
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
_hostingEnvironment = env;
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
var physicalProvider = _hostingEnvironment.ContentRootFileProvider;
var embeddedProvider = new EmbeddedFileProvider(Assembly.GetEntryAssembly());
var compositeProvider = new CompositeFileProvider(physicalProvider, embeddedProvider);
// choose one provider to use for the app and register it
//services.AddSingleton<IFileProvider>(physicalProvider);
//services.AddSingleton<IFileProvider>(embeddedProvider);
services.AddSingleton<IFileProvider>(compositeProvider);
}
}
EmbeddedFileProvider