Update: Rebex File Server 2017 R4 adds virtual file systems support. See the latest answer for details.
Although virtual file systems are not supported yet, Rebex File Server internals were designed with this scenario in mind and we plan to add a simple-to-use high-level API for this soon.
In the meantime, you can try Rebex File Server Beta with proof-of-concept IFilesystem API.
Customers with active support contract - write us an email to support@rebex.net to receive the full version of the beta. Please note that the API will most likely change for the official release.
To get started, just try the following code. It implements a FileServerEx
class that inherits from FileServer
, but wraps its filesystem object in a custom class that can be customized to do something else. For example, the OpenFile
method can be modified to return a custom IHandle
instead of calling _inner.OpenFile, and other methods that take IHandle can be enhanced to handle both custom and built-in IHandles. In your scenario, you will probably want to ignore the built-in IFilesystem implementations and write a custom filesystem that will enable you to open the virtual directory from database and then let users download the newsletter files that are physically located on the disk via the built-in IFileSystem implementation.
public class FileServerExt : FileServer
{
private class FilesystemWrapper : IFilesystem
{
private readonly IFilesystem _inner;
public FilesystemWrapper(IFilesystem inner)
{
_inner = inner;
}
void IFilesystem.Close(IHandle handle)
{
_inner.Close(handle);
}
void IFilesystem.CreateDirectory(string path)
{
_inner.CreateDirectory(path);
}
void IFilesystem.DeleteDirectory(string path)
{
_inner.DeleteDirectory(path);
}
void IFilesystem.DeleteFile(string path)
{
_inner.DeleteFile(path);
}
FilesystemInfo IFilesystem.GetFilesystemInfo()
{
return _inner.GetFilesystemInfo();
}
ItemInfo IFilesystem.GetItemInfo(string path)
{
return _inner.GetItemInfo(path);
}
string IFilesystem.Normalize(string absolutePath)
{
return _inner.Normalize(absolutePath);
}
IHandle IFilesystem.OpenDirectory(string path, string mask)
{
return _inner.OpenDirectory(path, mask);
}
IHandle IFilesystem.OpenFile(string path, FileOpenMode openMode, FileAccessMode accessMode)
{
return _inner.OpenFile(path, openMode, accessMode);
}
int IFilesystem.Read(IHandle handle, byte[] buffer, int offset, int count)
{
return _inner.Read(handle, buffer, offset, count);
}
ItemInfo IFilesystem.ReadNextItem(IHandle handle)
{
return _inner.ReadNextItem(handle);
}
void IFilesystem.Rename(string sourcePath, string targetPath)
{
_inner.Rename(sourcePath, targetPath);
}
string IFilesystem.ResolvePath(string path, string relativePath)
{
return _inner.ResolvePath(path, relativePath);
}
long IFilesystem.Seek(IHandle handle, FileSeekOrigin origin, long offset)
{
return _inner.Seek(handle, origin, offset);
}
void IFilesystem.SetItemInfo(string path, ItemInfo info)
{
_inner.SetItemInfo(path, info);
}
void IFilesystem.SetItemInfo(IHandle handle, ItemInfo info)
{
_inner.SetItemInfo(handle, info);
}
void IFilesystem.Write(IHandle handle, byte[] buffer, int offset, int count)
{
_inner.Write(handle, buffer, offset, count);
}
}
protected override IFilesystem GetFilesystem(ServerUser user)
{
IFilesystem inner = base.GetFilesystem(user);
IFilesystem outer = new FilesystemWrapper(inner);
return outer;
}
}
Please note that when using the FileServerExt class intead of FileServer class, user’s virtualRootPath still applies, making it possible for different users to access different parts of the custom filesystem.