How to get FileInfo objects from the Orchard Media folder?

289 views Asked by At

I'm trying to create a custom ImageFilter that requires me to temporarily write the image to disk, because I'm using a third party library that only takes FileInfo objects as parameters. I was hoping I could use IStorageProvider to easily write and get the file but I can't seem to find a way to either convert an IStorageFile to FileInfo or get the full path to the Media folder of the current tenant to retrieve the file myself.

public class CustomFilter: IImageFilterProvider {

    public void ApplyFilter(FilterContext context)
    {
        if (context.Media.CanSeek)
        {
            context.Media.Seek(0, SeekOrigin.Begin);
        }

        // Save temporary image 
        var fileName = context.FilePath.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault();

        if (!string.IsNullOrEmpty(fileName))
        {
            var tempFilePath = string.Format("tmp/tmp_{0}", fileName);
            _storageProvider.TrySaveStream(tempFilePath, context.Media);

            IStorageFile temp = _storageProvider.GetFile(tempFilePath);
            FileInfo tempFile = ???

            // Do all kinds of things with the temporary file

            // Convert back to Stream and pass along
            context.Media = tempFile.OpenRead();
        }
    }    
}

FileSystemStorageProvider does a ton of heavy lifting to construct paths to the Media folder so it's a shame that they aren't publicly accessible. I would prefer not to have to copy all of that initialization code. Is there an easy way to directly access files in the Media folder?

2

There are 2 answers

1
ub3rman123 On BEST ANSWER

I'm not using multitenancy, so forgive me if this is inaccurate, but this is the method I use for retrieving the full storage path and then selecting FileInfo objects from that:

_storagePath = HostingEnvironment.IsHosted
    ? HostingEnvironment.MapPath("~/Media/") ?? ""
    : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Media");

files = Directory.GetFiles(_storagePath, "*", SearchOption.AllDirectories).AsEnumerable().Select(f => new FileInfo(f));

You can, of course, filter down the list of files using either Path.Combine with subfolder names, or a Where clause on that GetFiles call.

This is pretty much exactly what FileSystemStorageProvider uses, but I haven't had need of the other calls it makes outside of figuring out what _storagePath should be.

In short, yes, you will likely have to re-implement whatever private functions of FileSystemStorageProvider you need for the task. But you may not need all of them.

0
ViRuSTriNiTy On

I was struggling with a similar issue too and i can say that the IStorageProvider stuff is pretty much restricted.

You can see this when viewing the code of FileSystemStorageFile. The class already uses FileInfo to return data but the struct itself isn't accessible and other code is based on this. Therefore you would have to basically reimplement everything from scratch (own implementation of IStorageProvider). The easiest option is to simply call

FileInfo fileInfo = new FileInfo(tempFilePath);

but this would break setups where no file system based storage provider is used like AzureBlobStorageProvider.

The proper way for this task would be to get your hands dirty and extend the storage provider interfaces and update all the code that is based on it. But as far as i can remember the issue here is that you need to update the Azure stuff also and then things get really messy. Due to this fact i aborted that approach when trying to do this heavy stuff on my project.