orchardcmsorchardcms-1.10

How to get FileInfo objects from the Orchard Media folder?


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?


Solution

  • 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.