ZippingSitecoreLogsI’ve decided to 1-up the game from my previous post and zip something that isn’t really a real file but rather a blob in a Sitecore database. The script below is based heavily on the last post but instead of just zipping content of a flat folder traverses the Sitecore item tree and zips all files beneath the current folder.

If you have downloaded the 2.1 version of the Sitecore PowerShell Console from the Sitecore Marketplace you will actually have the script deployed on your system already.

Here’s how it looks like for your user in the Content Editor:

ZipAndDownloadContextMenu

The script that performs the operation looks as follows:

###########################################################################
#                                                                         #
# The script zips all files in the media library under the current folder #
# and allows users to download the zip.                                   #
#                                                                         #
###########################################################################
 
#
# The ZipFiles function is based on noam's answer
# on the following Stack Overflow's page: http://bit.ly/PsZip
#
function ZipItems( $zipArchive, $sourcedir )
{
  Set-Location $sourcedir
  [System.Reflection.Assembly]::Load("WindowsBase,Version=3.0.0.0, `
      Culture=neutral, PublicKeyToken=31bf3856ad364e35") | Out-Null
  $ZipPackage=[System.IO.Packaging.ZipPackage]::Open($zipArchive, `
      [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::ReadWrite)
  $items = gci -recurse $sourceDir
  [byte[]]$buff = new-object byte[] 40960
  $i = 0;
  ForEach ($item In $items) {
    $i++
    if([Sitecore.Resources.Media.MediaManager]::HasMediaContent($item)){
      $mediaItem = New-Object "Sitecore.Data.Items.MediaItem" $item;
      $mediaStream = $mediaItem.GetMediaStream();
      $fileName = Resolve-Path -Path $item.ProviderPath -Relative
      $fileName = "$fileName.$($item.Extension)" `
        -replace "\\","/" -replace "./", "/"
      # Print out the file - the list will show up once the file is downloaded
      "Added: $fileName"
      # Show progress for the operation
      Write-Progress -Activity "Zipping Files " `
        -CurrentOperation "Adding $fileName" `
        -Status "$i out of $($items.Length)" `
        -PercentComplete ($i *100 / $items.Length)
      $partUri = New-Object System.Uri($fileName, [System.UriKind]::Relative)
      $partUri = [System.IO.Packaging.PackUriHelper]::CreatePartUri($partUri);
      $part = $ZipPackage.CreatePart($partUri, `
        "application/zip",  `
        [System.IO.Packaging.CompressionOption]::Maximum)
      $stream=$part.GetStream();
      do {
        $count = $mediaStream.Read($buff, 0, $buff.Length)
        $stream.Write($buff, 0, $count)
      } while ($count -gt 0)
      $stream.Close()
      $mediaStream.Close()
    }
  }
  $ZipPackage.Close()
}

#the location will be set by PowerShell automatically based on which item was clicked
$location = get-location
$dateTime = Get-Date -format "yyyy-MM-d_hhmmss"
$zipName = Split-Path -leaf $location | % { $_ -replace " ", ""}
$dataFolder = [Sitecore.Configuration.Settings]::DataFolder
$zipPath = "$dataFolder\$zipName-$datetime.zip"

# Call the Zipping function
ZipItems $zipPath $location

#Send user the file, add -NoDialog if you want to skip the download dialog 
Download-File -FullName $zipPath | Out-Null

# Cleanup after yourself
Remove-Item $zipPath

# Close the results window - we don't really need to see the results
Close-Window

And here’s what your user will show after it gets run:

ZipAndDownloadMediaLibrary

Yep, the script actually shows progress while the files are being zipped and then pops up the download dialog showing you the file size, quite rich experience for less than 50 lines of code, eh?

Now how do we integrate the script with the Content Editor?

All you really need to do is Save the script in the proper place in the library:

ZipAndDownloadScriptLibrary

Once the Script is saved, we can limit the script to be available only when you right click on items in in the Media Library by editing the script Runtime properties:

ZipAndDownloadScriptProperties

Happy scripting!

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 4.50 out of 5)
Loading...



This entry (Permalink) was posted on Monday, July 15th, 2013 at 11:00 pm and is filed under Code Samples, Downloadable, Open Source, PowerShell, Sitecore, Software Development, Solution, Web applications. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response , or trackback from your own site.



  • Mark Gurevich

    Hi Adam,

    I am having a bit of hard time with “zip and download sitecore media library folder” tool.
    Using Sitecore 6.6 and SPE 2.4 (the earliest I could find).
    I am trying to zip up media library. While it works for sub folders under media library, I get empty archive if try to run the command on the whole Media Library folder. Also, I see this error in Sitecore log.

    ManagedPoolThread #16 13:51:47 ERROR Error while executing GetChildItems(string path=’master:media library’, string recurse=’True’)

    Include the complete version of the script that was installed for me the package installer bellow.

    Any suggestions are much appreciated.

    Best
    Mark

    function ZipItems( $zipArchive, $sourcedir )
    {
    Set-Location $sourcedir
    [System.Reflection.Assembly]::Load(“WindowsBase,Version=3.0.0.0, `
    Culture=neutral, PublicKeyToken=31bf3856ad364e35”) | Out-Null
    $ZipPackage=[System.IO.Packaging.ZipPackage]::Open($zipArchive, `
    [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::ReadWrite)
    $items = gci -recurse $sourceDir
    [byte[]]$buff = new-object byte[] 40960
    $i = 0;
    ForEach ($item In $items) {
    $i++
    if([Sitecore.Resources.Media.MediaManager]::HasMediaContent($item)){
    $mediaItem = New-Object “Sitecore.Data.Items.MediaItem” $item;
    $mediaStream = $mediaItem.GetMediaStream();
    $fileName = Resolve-Path -Path $item.ProviderPath -Relative
    $fileName = “$fileName.$($item.Extension)” -replace “\”,”/” -replace “./”, “/”
    “Added: $fileName”
    Write-Progress -Activity “Zipping Files ” -CurrentOperation “Adding $fileName” -Status “$i out of $($items.Length)” -PercentComplete ($i *100 / $items.Length)
    $partUri = New-Object System.Uri($fileName, [System.UriKind]::Relative)
    $partUri = [System.IO.Packaging.PackUriHelper]::CreatePartUri($partUri);
    $part=$ZipPackage.CreatePart($partUri, “application/zip”, [System.IO.Packaging.CompressionOption]::Maximum)
    $stream=$part.GetStream();
    do {
    $count = $mediaStream.Read($buff, 0, $buff.Length)
    $stream.Write($buff, 0, $count)
    } while ($count -gt 0)
    $stream.Close()
    $mediaStream.Close()
    }
    }
    $ZipPackage.Close()
    }

    $location = get-location
    $dateTime = Get-Date -format “yyyy-MM-d_hhmmss”
    $zipName = Split-Path -leaf $location | % { $_ -replace ” “, “”}
    $dataFolder = [Sitecore.Configuration.Settings]::DataFolder
    $zipPath = “$dataFolder$zipName-$datetime.zip”

    ZipItems $zipPath $location
    Download-File -FullName $zipPath | Out-Null
    Remove-Item $zipPath
    Close-Window