Displaying file size for your MediaData

Creating a document link as file.pdf(230kB ) may seem like a simple task…

Well now it is…

My Generic media

public class GenericMedia : MediaData
{
[CultureSpecific]
[Display( Name = "Title-text",
Description = "Ange title-text",
GroupName = SystemTabNames.Content, Order = 2)] 

public virtual String Description { get; set; }
public virtual string Copyright { get; set; }
[Editable(false)]
public virtual string FileSize { get; set; } }

Helper to get the file size


 public static string GetFileSize(GenericMedia media)
        {
            if (media != null)
            {
                using (var stream = media.BinaryData.OpenRead())
                {
                    return (stream.Length /1024)+ " kB";
                }
            }
            return string.Empty;
        }

And som magic sprinkle of events


namespace proj.Business.Initialization
{
    [InitializableModule]
    [ModuleDependency(typeof (EPiServer.Web.InitializationModule))]
    public class InitializationModule : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            var eventRegistry =
            ServiceLocator.Current.GetInstance<IContentEvents>();

            eventRegistry.CreatingContent += OnCreatingContent;
            eventRegistry.SavingContent += OnSavingContent;

        }

        public void Preload(string[] parameters)
        {
        }

        public void Uninitialize(InitializationEngine context)
        {
            var eventRegistry =
            ServiceLocator.Current.GetInstance<IContentEvents>();

            eventRegistry.CreatingContent -= OnCreatingContent;
            eventRegistry.SavingContent -= OnSavingContent;

       }

        private void OnSavingContent(object sender, ContentEventArgs e)
        {
            var content = e.Content as GenericMedia;
            if (content == null)
                return;
            var fs = ContentHelpers.GetFileSize(content);
            content.FileSize = fs;
        }

        private static void OnCreatingContent(object sender, ContentEventArgs e)
        {
            var content = e.Content as GenericMedia;
            if (content == null)
                return;
            var fs = ContentHelpers.GetFileSize(content);
            content.FileSize = fs;
        }
    }
}

 

Usage


<a title="@content.Description" href="@UrlResolver.Current.GetUrl(content.ContentLink)">
@content.Name (@content.FileSize)</a>

Enjoy!

13 thoughts on “Displaying file size for your MediaData

    1. Hi, I have tried that approach with no success I did not use the backing type how ever. Have you accomplished the same result using the getter then please share.

      It would be interesting to see. In my case I will probably need to do some other stuff with my GenericMedia upon saving it so its not to much overhead using the event approach. But i can concur that it seems like an overkill for this simple task.

  1. Could you also, the same way, show the any other file-related metadata such as “Last Modified Date”? I just had this request from a customer earlier this week.

    1. Last modified date should be available directly on the MediaData object i think? This approach is better suited for saving meta data the first time the file is uploaded or updated.
      You don’t want to do unnecessary stream io operations just to get the file size, therefor it is saved in a separate property.

      But the answer is yes.
      /D

  2. Vladis thats a good question =)
    I think that the onSaving should handle if they somehow changed the file with a different size but same filename.

    Otherwise the onCreating should bee sufficient for the task.

    1. If you add a new file, it calls OnCreating. If you add the same file, onSaving gets called. For me (int 7.7, the code for onSaving issues an exception in this line of code content.FileSize = fs;, so I needed to create a writable clone of the page first:

      private void InstanceSavingContent(object sender, ContentEventArgs e)
      {
      var genericMedia = e.Content as GenericMedia;

      if (genericMedia != null)
      {
      using (var stream = genericMedia.BinaryData.OpenRead())
      {
      var sizeInBites = stream.Length;
      var contentRepo = ServiceLocator.Current.GetInstance();
      var fileSize = StringExtensions.BytesToString(sizeInBites);

      if (fileSize != genericMedia.Size)
      {
      var writableGenericMedia = (GenericMedia)genericMedia.CreateWritableClone();
      writableGenericMedia.Size = fileSize;
      contentRepo.Save(writableGenericMedia, SaveAction.Save, AccessLevel.Edit);
      }
      }
      }
      }

      1. Marija are you using any other attributes for hiding FileSize for the editors like Ignore or Scaffold false?
        You should not need to do the writeble clone inside the events.

        I have this working on 7.6, will upgrade and check.
        /Daniel

      2. I don’t have anything, but it might be that I used to have Scaffold false that still affected what’s in DB. I’ll check that, thx

  3. Great post. One thing you could consider is using an interface for the file size property like IFileSize or similar. That way your code could then cater for any type of MediaData.

    if (content == null)
    return;
    var fs = FileReader.GetFileSize(content);

    var mediaFile = content as IFileSize;
    mediaFile.FileSize = fs;

Leave a comment