Bulk Loading Images in Sitecore Media Library Using Sitecore Powershell Extension (SPE)

With the blessings from Sitecore Powershell gurus Adam NajmanowiczMichael West and Mike Reynolds, this is my first blog post on Sitecore Powershell Extension (SPE). I mean it. When I had a problem to solve and I wanted to use SPE for that, I just dropped a question in Twitter and the help was more than what I expected.  They helped me all the way to solve my problem. These guys are awesome. I love Sitecore community.

So, what problem I was trying to solve using SPE? We have an application where, we have more than 10 thousands product items. We have to load and associate the images for those product items in Media Library. Why use SPE? Because, I cannot imagine a content editor loading images using Media Library uploader. Media Library does upload images from zip file. In my case the requirement doesn’t stop on just loading the images. We need to associate images to the product items, which I did using my SPE script. Beside this, since this a SPE is script, we can run it via Sitecore Schedule Task. All the user needs to do is drop the images in the designated folder.

For this blog, I will only describe how loading images in bulk works. Rest of the program of associating images to product items is very specific to our requirement and better not discussed for the sake of keeping length of blog smaller. While working on this problem, I faced couple of issues. Those were solved with the help of SPE team. I described the issues at the end of the blog, in case someone looking for answers.

My research started with this article written by Adam. This describes, how a remote SPE script can be run to load image from the file system to media library. I needed to extend this functionality. The first thing I did was created my own Powershell function that loads multiple images from the file system. Here is the script.

#You need to include cmdlets from following location before using this function
#Invoke-Script 'master:/sitecore/system/Modules/PowerShell/Script Library/Platform/Functions/Remoting'
function Upload-MultipleImages {
    [CmdletBinding()]
    param(
        #Remote site host name
        [Parameter(Position=0, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$SiteUrl,
        
        #Remote site username
        [Parameter(Position=1, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Username,

        #Password for above username
        [Parameter(Position=2, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Password,

        #Folder location in the File System where images are located
        [Parameter(Position=3, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$SourcePath,

        #Image file extension jpg, png etc.
        [Parameter(Position=4, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$FileExtension,

        #Media Library location
        [Parameter(Position=5, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [String]$MediaPath

    )
    #Connect to Remote Sitecore site
    Set-SitecoreConfiguration $SiteUrl $Username $Password
    #Get all the Image file names
    $images=Get-ChildItem "$SourcePath*.$FileExtension" -name
    foreach($image in $images)
    {
        $MediaImagePath="$MediaPath$image"
        #Check if the image already exists in the Media Library location.
        #If exists, skip it but log in the Sitecore log file and in the console
        #If doesn't exists, upload the image and log the message
        if(Test-Path $MediaImagePath.TrimEnd(".$FileExtension"))
        {
            Write-Log "Image $Image already exists... skipping"
            Write-Host "Image $Image already exists... skipping"
        }
        else
        {
            Write-Log "Uploading Image $Image ..."
            Write-Host "Uploading Image $Image ..."
            Upload-SitecoreFile -remotePath $MediaImagePath -File "$SourcePath$image"
            Write-Log "Uploading Image $Image ... done."
            Write-Host "Uploading Image $Image ... done."
        }
    }
}

Once this function was created, I created below script to call the above function.

#Include SPE remoting scripts
Invoke-Script 'master:/sitecore/system/Modules/PowerShell/Script Library/Platform/Functions/Remoting'
#Include my function
Invoke-Script 'master:/sitecore/system/Modules/PowerShell/Script Library/Nishtech/Functions/Upload-MultipleImages'
$StartTime=Get-Date
#Get context item
$item=Get-Item .
#Get full path of the context item (media folder)
$MediaPath=$item.FullPath
Upload-MultipleImages 'http://myapp.local.com' 'admin' 'b' 'C:\Work\Project Docs\myapp\Images\' 'jpg' "$MediaPath/"
$EndTime=Get-Date
#Show total time taken
new-timespan -Start $StartTime -End $EndTime

I added the above script in the location showed in the following image.

 ScriptLocation

The reason to store the script there was to use Context Menu, like below. I can right click on any media folder and run the script from the context menu.

ContextMenu

I also added a rule for the script so that the context menu only shows up for the Media Library folders.

Rule

The context menu will not show up if the Module was not activated. Make sure the following option checked for the Module where script has been stored.

ModuleActivation

Now, if I run the script from the context menu, it runs and shows me the following progress box.

ProgressBox

If I click on the ‘View Script Results’ link, I can see the result in the SPE console window snapshot.

ConsoleI wanted to run the same script from the Schedule Task. I had to create a separate script for that because, in this case there is no context media folder. I need to pass the destination folder in from the script itself. Same script, only change is the following line.

Upload-MultipleImages ‘http://myapp.local.com’ ‘admin’ ‘b’ ‘C:\Work\Project Docs\Myapp\Images\’ ‘jpg’ ‘master:/sitecore/media library/Images/Products’

Here is the scheduled task settings

ScheduledTask

That’s all I had to do for loading images.

Issues:

As I mentioned in the beginning that I faced couple of issues working on this. I will discuss them now. I learned few things from these issues.

Routing Issue:

One of my application included in the Sitecore desktop has the path that contains /Console/. After installing SPE, I found that this application stopped working and I was getting following error.

RoutingError

I opened up Cognifide.PowerShell.Core.Processors.RewriteUrl in DotPeek and found that following code in the preprocessorRequest pipeline is looking for any route that includes ‘/Console/’ and re-writing it with “/sitecore modules/PowerShell/”

        Uri url = arguments.Context.Request.Url;
        string localPath = url.LocalPath;
        if (localPath.StartsWith("/Console/", StringComparison.OrdinalIgnoreCase))
          WebUtil.RewriteUrl(new UrlString()
          {
            Path = localPath.ToLowerInvariant().Replace("/console/", "/sitecore modules/PowerShell/"),
            Query = url.Query
          }.ToString());

The solution was to write my own processor and replace the SPE processor with that. I just changed the code to look for more specific route “/Console/Services/”. Simple fix.

        Uri url = arguments.Context.Request.Url;
        string localPath = url.LocalPath;
        if (localPath.StartsWith("/Console/Services/", StringComparison.OrdinalIgnoreCase))
          WebUtil.RewriteUrl(new UrlString()
          {
            Path = localPath.ToLowerInvariant().Replace("/console/", "/sitecore modules/PowerShell/"),
            Query = url.Query
          }.ToString());

 No Rules Available in the Rules Editor:

When I tried to set the Rule for my script I found that there is no out of the box Sitecore rules in the Rules Editor. Adam pointed me that there is patch exists in the Sitecore Marketplace download area for this issue. After I installed that patch, the rules started showing up.

RulesPatch

Final Words:

This is my first encounter with Sitecore Powershell and I am extremely excited by realizing it’s usefulness in Sitecore projects. I will be using it in future and keep blogging about it.

References:

Advertisements

About Himadri Chakrabarti

I am a software developer architect and a Sitecore MVP. My professional interest is everything and anything related to Software Architecture, .NET, Sitecore, Node.js, NoSQL etc. Outside of my profession, I am a hobbyist photographer. Link to my photography site http://himadriphotography.com/
This entry was posted in Powershell, Sitecore and tagged , . Bookmark the permalink.

2 Responses to Bulk Loading Images in Sitecore Media Library Using Sitecore Powershell Extension (SPE)

  1. Pierre says:

    Hi Himadri,
    Thanks for this, would be very useful for me as well. I’m getting an error though with the local path. Does $SourcePath is a path on the server where the sitecore instance is hosted or on your local machine?
    best,
    Pierre

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s