If you need to upload an image into Episerver's media library programmatically, then this tutorial is for you.  

The ContentAssetHelper Introduced

Before we go into the code to upload media, we need to consider where within Episerver we want to upload the asset into. As a general rule of thumb, you have two options when dealing with a media library, you can use a general folder(s) organised how you want to upload your content that you can access from anywhere in the site, or you can associate your assets against a specific page/content reference that are exclusive to that particular instance. In order to programmatically work with Episerver's media folder, let's introduce the ContentAssetHelper. The ContentAssetHelper allows you to do all things media library related within Episerver, like getting references to folders, create new folders etc...  For example, to create a new asset folder associated with a page, you would call the API like this:

               var contentReferenceToMyPage = new ContentReference();
               var contentAssetHelper = ServiceLocator.Current.GetInstance<ContentAssetHelper>();
               var contentAssetReference = contentAssetHelper.GetOrCreateAssetFolder(contentReferenceToMyPage);

The ContentRepository Also Works With Media!

If you've worked with Episerver a little bit, then you'll know that you use the content repository API to query Episerver in order to get pages and blocks.  Since Episerver 7, all items within Epi, whether they be pages, blocks, or media assets like images and PDF are considered content.  If you are unsure about how you define allowed media types within Episerver, then I suggest you read this tutorial.  When you load an image or a media file into Episerver, it will be treated as content, it will have a content reference and consequently, you will also be able to get assets using it.  For example, this bit of code will get an image:

            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var imageReference = new ContentReference();
            var image = contentRepository.Get<MediaData>(imageReference);

Where are my media files stored?

Up to this point, I think the discussion is fairly intuitive and easy to understand, so to recap.  When we work with media in Episerver we first need to define the types that content editors are allowed to use.  In order for content editors to be able to work and use that media within the editor, we need to associate our media files into folders.  We can then use the normal content repository to access that media.  

The last part of the media puzzle, which you might have missed, is where exactly is this media stored?!?!  This is a great question.  When we work with Episerver, we might be using DXC, we might be using Azure, we might even be using a more traditional infrastructure set-up, with on-prem servers, configured in a load balancer.  As Episerver can be hosted in a number of different ways, uploading the actual files isn't as straightforward as simply copying them into a folder in your website's webroot.  Instead, in Episerver we upload your files as blobs, using the BlobFactory.

In case you've never heard of a blob, it stands for Binary Large Objects, in other words, it's just a fancy way of saying 'files.  As far as I'm aware (prob should Google this, but hey) it came from a database terminology.  In SQL, if you want to store a file within your database, the type you'd use was called a blob.  Obviously, uploading several Gigabytes of data into a database is a bad idea, so don't do it!

Any file type can be stored in BLOB service, e.g. images, text files, etc...  Back in Epi 6, you would specify your blog storage folder within the Episerver VPP folder which sat somewhere on your server or a NAS.  From Epi 7 onwards, as Episerver moved towards a more continuous integration deployment strategy, by default the blog folder will be located in your App_data folder.  All of the blob location is customizable, so you can decide where you want to store the files. Nowadays, most sites I build seem to be hosted within the cloud, using Azure blob storage and the location of the file is 'in the cloud'.

To save a file with the blob storage, you would use a snippet like this:

            var filePath = "C:/file.jpg";
            var imageExtension = ".jpg";

            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var newImage = contentRepository.GetDefault<MediaData>(SiteDefinition.Current.GlobalAssetsRoot);

            var blobFactory = ServiceLocator.Current.GetInstance<IBlobFactory>();
            var byteArrayData = File.ReadAllBytes(filePath);

            var blob = blobFactory.CreateBlob(newImage.BinaryDataContainer, imageExtension);
            using (var s = blob.OpenWrite())
                var w = new StreamWriter(s);
                w.BaseStream.Write(byteArrayData, 0, byteArrayData.Length);

            newImage.BinaryData = blob;
            contentRepository.Save(newImage, SaveAction.Publish);           

You can either get your media asset from your local file system, or you could use a WebClient to get the file from the interweb, but that pretty much covers all the API's and steps that you need to follow in order to upload an image, or media file via code with Episerver, enjoy!