KNOWLEDGE BASE

Moving Umbraco media from one Azure blob storage to another


I've just been working upon an existing Umbraco 7 site that has been upgraded from around 7.2.4 to 7.11.1. This instance is hosted in a third party's Azure account (lets call them ripoff.com) where the client was being charged an extortionate amount of money each month, hence we decided to move to their own account. 

Key issues to resolve

  1. One of the issues we had was the media had been uploaded into the Azure subscription run by ripoff.com and we needed to migrate it over to our own account.
  2. Another was then to ensure the references for the Umbraco media was updated to reflect the new root url i.e. https://ripoff.blob.core.windows.net/media/1475/game.jpg to https://newone.blob.core.windows.net/media/1475/game.jpg 

Pre-requisites

You will need access to the old and new Azure subscriptions

You will need access to the files upon your server instance

You will need to connect SQL Server Management studio to your site

YOU WILL NEED TO BACKUP EVERYTHING FIRST :-) Have a rollback plan in place should anything go wrong! We will not be held responsible for anything you mess up.

How did we do it?

The following is the steps we undertook in order to achieve this:

  1. Download and install Microsoft Azure Storage Explorer - a brilliant little tool (cross platform as well, i did all this from my Mac!). Download from Microsoft here https://azure.microsoft.com/en-gb/features/storage-explorer/
  2. Configure the tool and connect to both instances - you can do this in the one instance (especially if you use the same login for both instances)
  3. Open up the source storage account / Blob Containers / media folder - you should now see all the folders and files for your media.
  4. Right click on media and select Copy Blob Container
  5. Open up your target storage account / Blob Containers, right click and select Paste Blob Container - leave it to do it's stuff (view progress in the activities window below).
  6. Once this is 100% complete, congratulations, you have copied your media over! Easy part done.

Tell Umbraco how to get the data

  1. In Azure blob explorer, select the media storage container on your target instance
  2. In the bottom panel, you should see an Actions / Properties tab. Select properties and copy the URL - this is the url to your new media folder.
  3. In your Umbraco site, open up the FileSystemProviders.config file and update the Root URL with the url obtained in step 1 (remove the media/ part) and for the container name setting, set this to media. Finally update the connection string (you can get this from the Azure portal or via the Blob Explorer window - see the properties area for Primary Connection String). Save this file.

If you now goto your media section and upload a new image, it *should* use the new blob storage settings and save to the new location - check this by looking at the generated URL or use Chrome inspector to check the url for the thumbnails.

Now you would think that is it, unfortunately not. In theory the Umbraco provider should read out this value when dishing out the media url and append the new blob storage url, alas it's never that simple in Umbraco land so this is what I had to do to get it all working.

This means that ALL your existing images will still be hardcoded to use the old storage URL - not great by any stretch. Whilst sorting this, I came across a post on Our that had similar issues, I then took a couple of the posts, tweaked them and came up with a new solution for doing this.

What actually happens is that the database stores hard links to the original source so in our case, we had hundreds (actually thousands) of references to the ripoff link that we needed to change.

What follows at the end of the post is the SQL Statements we ran, in order, to fix this. Please backup your DB first, this could cause a major screwup if you get this wrong! Finally it's a good idea to republish all the media, John Ligtenberg posted a class that achieves this and tells you at the end how many it's published. This way the front end should then see the new blob storage urls, the back office media section should display all the thumbnails and everything should just *work*.

It worked for us, the site was moved over and ripoff agency was relieved of itss duties. Hope it helps you out, however if you are still stuck or this is too technical for you, give me a call on 07967739393 or [email protected] and I can book in some consultancy time to do it for you!

 

 

 

1. update cmsPropertyData 
set dataNvarchar = cast(replace(cast(dataNvarchar as nvarchar(max)), 'http://ripoff.blob.core.windows.net/media/', 'https://newone.blob.core.windows.net/media/') as nvarchar(max)) 
where dataNvarchar like 'http://ripoff.blob.core.windows.net/media/%' 


2. update cmsContentXml 
set xml = cast(replace(cast(xml as nvarchar(max)), 'http://ripoff.blob.core.windows.net/media/', 'https://newone.blob.core.windows.net/media/') as ntext) 
where xml like '<Image%' or xml like '<File%'


3. update cmsContentXml 
set xml = cast(replace(cast(xml as nvarchar(max)), '"src": "http://ripoff.blob.core.windows.net/media/', '"src": "https://newone.blob.core.windows.net/media/') as ntext)
go

4. update cmsPropertyData 
set dataNText = cast(replace(cast(dataNText as nvarchar(max)), '"src": "http://ripoff.blob.core.windows.net/media/', '"src": "https://newone.blob.core.windows.net/media/') as ntext) 
go

5. Create a file called publish.cs, place in your app_code folder and paste in the following code. Call the code by using the url http://yoursite/umbraco/api/media/publish (thanks to John Ligtenberg for this code). 

using System.Web.Mvc;
using System.Linq;

public class MediaController : Umbraco.Web.WebApi.UmbracoApiController
{
    [System.Web.Http.AcceptVerbs("GET", "POST")]
    [System.Web.Http.HttpGet]
    public string Publish()
    {
        var mediaCounter = 0;

        if (ApplicationContext.Services != null)
        {
            var ms = ApplicationContext.Services.MediaService;

            for (int i = 0; i < 10; i++)
            {
                var media = ms.GetByLevel(i).ToList();

                if (media.Any())
                {
                    foreach (var item in media)
                    {
                        ms.Save(item);
                        mediaCounter++;
                    }    
                }                    
            }               
        }

        return mediaCounter.ToString();
    }
}                                    

Need an Umbraco Master?

Here at Simon Antony, we have an in house certified Umbraco Grand Master available for hire. Got a problem with your site, need architecture advice, give us a call to speak to Simon directly and see how we can help

Contact Simon Today!