Reputation: 1010
I have different ASP.NET Core (non MVC) applications, which serve multiple static Angular applications.
I use the PhysicalFileProvider class do so, which works fine.
// This works fine!
var fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "NG", "UI", "Login"));
var options = new FileServerOptions
{
FileProvider = fileProvider,
RequestPath = "/ng/ui/login",
EnableDirectoryBrowsing = true
};
However, before delivering these static files to the client, I need to change some of these files in the RAM, without changing them physically on the disk.
I already wrote my own implementation of a physical file provider, but I don't understand at which point of time or where the files are actually read from the disk.
PhysicalFileProvider has basically just two or three functions, which seem to deliver only informations about files, but not the actual files as bytes.
// These two functions of PhysicalFileProvider only deliver informations, but not the files? Am I
wrong?
IDirectoryContents GetDirectoryContents(string subpath)
IFileInfo GetFileInfo(string subpath)
My question is: What kind of middleware needs to be hooked in the ASP.NET service pipeline, to change a static file (let's say a simple text file) in the RAM before delivery?
Thanks for any hints!
Upvotes: 1
Views: 87
Reputation: 141565
Personally I would go with approach of serving the files via "ordinary" action/handler (probably with catch-all route) or probably some middleware (for example a one "intercepting" the actual requests for files.) but if you want to try solving this with file provider then you need to work with two interfaces IFileProvider
and IFileInfo
:
class MyFileProvider : IFileProvider
{
private readonly string _root;
private readonly PhysicalFileProvider _provider;
public MyFileProvider(string root)
{
_root = root;
_provider = new PhysicalFileProvider(_root);
}
public IDirectoryContents GetDirectoryContents(string subpath)
=> _provider.GetDirectoryContents(subpath);
public IFileInfo GetFileInfo(string subpath)
{
var fileInfo = _provider.GetFileInfo(subpath);
return new MyFileInfo(fileInfo);
}
public IChangeToken Watch(string filter)
{
throw new NotImplementedException();
}
}
class MyFileInfo : IFileInfo
{
private static readonly ReadOnlyMemory<byte> ToAppend
= new(" Hello World!"u8.ToArray());
private readonly IFileInfo _fileInfo;
public MyFileInfo(IFileInfo fileInfo) => _fileInfo = fileInfo;
public bool Exists => _fileInfo.Exists;
public bool IsDirectory => _fileInfo.IsDirectory;
public string Name => _fileInfo.Name;
// magic is done in the following parts:
// original file modification:
public Stream CreateReadStream()
{
var readStream = _fileInfo.CreateReadStream();
var memoryStream = new MemoryStream();
readStream.CopyTo(memoryStream);
memoryStream.Write(ToAppend.Span);
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
// disables caching like behavior
public DateTimeOffset LastModified => DateTimeOffset.UtcNow;
// needed to serve correct length of the file
public long Length => _fileInfo.Length + ToAppend.Length;
// otherwise will try serving file from disk as is as far as I can see
public string? PhysicalPath => null;
}
And register it:
var myFileProvider = new MyFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"MyStaticFiles"));
app.UseFileServer(new FileServerOptions()
{
FileProvider = myFileProvider,
RequestPath = new PathString("/StaticFiles"),
EnableDirectoryBrowsing = true
});
This is a sample implementation just for demonstration purposes which is far from perfect - it appends " Hello World!"
to the served files, for example for example file containing text Test
result is:
Upvotes: 4