Migrer des fichiers multimédia d’un stockage de compte Azure a un autre

Un de nos clients mettait à niveau son installation Sitecore multisite / multilingue de la version 9.0.1 à 9.3, et devait migrer des gigaoctets de fichiers multimédia.

Bien sûr, transf´érer les éléments Sitecore était facile, il suffit simplement de créer un package et de l’importer sur le nouveau site – je vais vous montrer comment faire cela ici – mais le vrai défi était d’importer les fichiers de la médiathèque. Les anciens fichiers se trouvaient dans un compte de stockage Azure et nous devions attacher les fichiers corrects aux nouveaux éléments Sitecore, afin qu’ils obtiennent une référence au nouveau compte de stockage.

Un autre défi consistait à identifier les éléments Sitecore qui font directement référence aux fichiers de l’ancien compte de stockage Azure, comme on peut le faire par exemple dans un éditeur de texte enrichi

Imaginons que vous ayez cet ancien site S1, avec vos éléments de contenu dans /sitecore/content/Sites et vos éléments multimédias dans /sitecore/media library/Sites. Les éléments multimédias sont stockés dans un compte de stockage Azure (S1.blob.core.windows.net).

Nous allons créer un package pour les éléments de contenu Sitecore, un autre pour les éléments de la médiathèque Sitecore. Ensuite, nous obtiendrons les fichiers multimédias d’Azure. À l’aide d’un script Powershell, nous importerons les fichiers multimédias dans le nouveau compte de stockage Azure et les référencerons aux éléments Sitecore du nouveau site.

Etape 1: Creer deux packages

Pour créer un package, accédez à Sitecore Desktop et choisissez Démarrer / Outils de développement / Concepteur de packages

Je vous recommande de créer deux packages distincts, un pour vos éléments de contenu (sous /sitecore/Content) et un pour vos éléments de bibliothèque multimédia (sous / sitecore/media library).

Dans l’application Package Designer, ajoutez des éléments de manière statique

Lorsque vous avez terminé d’ajouter des éléments à ce package, entrez un bon nom de source (comme ContenuSite1). Vous êtes de retour à la fenêtre principale de l’application Package Designer. Entrez un nom de package et un auteur, car ces informations seront présentées lors de l’installation de votre package.

Cliquez ensuite sur le bouton “Générer ZIP” pour créer votre fichier zip. N’oubliez pas de télécharger le package à la dernière étape!

Procédez de la même manière pour créer un package pour les éléments de la bibliothèque multimédia sous /sitecore/media library/Sites.

Le package multimédia comprend en fait des binaires (blobs) pour tous les fichiers multimédias. Nous n’en avons pas besoin sous cette forme, car nous allons migrer ces fichiers a l’aide d’un script d’un stockage Azure vers un autre. À l’aide d’un outil zip (j’utilise 7-zip), ouvrez le package et supprimez l’objet blob du dossier. Le nouveau package multimédia sera également beaucoup plus petit et donc plus rapide à installer.

Etape 2 – Importer les fichiers multimédias du Azure Storage Account

Connectez-vous à votre compte Azure et accédez au compte de stockage Azure. Pour avoir les autorisations d’importer les fichiers, vous devez créer une signature d’accès partagé (SAS)

Dans le portail Azure, identifiez et ouvrez votre Storage Account. Dans le menu de gauche, cliquez sur “Shared access signature”

Choisissez le type de types de ressources que vous serez autorisé à télécharger et générez votre chaîne SAS.

Enregistrez la valeur du champ “SAS token”, c’est ce dont vous aurez besoin plus tard

Je vais utiliser l’utilitaire azcopy. Si vous ne l’avez pas déjà installé, faites-lehttps://aka.ms/downloadazcopy-v10-windows

Ouvrez une console Powershell en tant qu’administrateur.

Vous devez d’abord vous connecter à votre compte Azure à partir de la console Powershell. Tapez la commande “az login” et suivez les instructions pour vous connecter.

L’instruction pour obtenir tous les fichiers multimédias du compte de stockage Azure est

azcopy copy 'https://{STORAGE_ACCOUNT_SERVER}/medialibrary/Sites/{SAS_KEY}' '{LOCAL_PATH}' --recursive

Tous les fichiers du compte de stockage sont maintenant transférés vers votre dossier local, en conservant la hiérarchie des dossiers.

Etape 3 – Téléchargez les fichiers multimédias sur le serveur Sitecore CM

Il est recommandé de toujours utiliser le même dossier sur le site Web de Sitecore lorsque vous avez des fichiers à transférer. J’utilise toujours le dossier $SitecoreDataFolder/upload (aka /App_Data/upload) pour déplacer des fichiers.

Si vous avez une installation sur site (on Promises), il est très facile de transférer vos nouveaux fichiers multimédias directement vers le dossier de téléchargement avec FTP ou un dossier partagé.

Si votre serveur CM est un Azure App Service, vous devez obtenir les paramètres de publication du serveur CM pour disposer des informations de connexion FTP. À l’aide d’Azure Portal, surfez sur la page contenant toutes les informations sur votre serveur CM. Restez sur la page Présentation/Overview et cliquez sur le bouton “Obtenir le profil de publication”/”Get publish profile”

Le profil de publication est un fichier XML contenant des informations d’identification pour se connecter à ce serveur avec FTP.

Le nom de profil “SERVERNAME – FTP” est celui que vous devez regarder. L’attribut “publishUrl” est l’URL de connexion, “userName” est le nom d’utilisateur et “userPWD” est le mot de passe. Utilisez ces informations pour placer tous les fichiers multimédias dans le dossier /App_Data/upload du serveur.

Etape 4 – Installer les éléments Sitecore

Installez les packages nouvellement créés sur le serveur CM, à l’aide de l’assistant d’installation des packages

Etape 5 – Executez le script SPE

Il est maintenant temps de joindre les fichiers aux éléments Sitecore et de transférer ces fichiers vers Azure Storage. Pour connecter les éléments Sitecore et les fichiers, mon script recherche un élément Sitecore avec le même nom que le fichier, et dans un chemin correspondant. Si vous avez une autre structure dans vos fichiers et dans vos éléments SItecore dans la médiathèque, vous devrez modifier la commande de recherche dans la fonction Find-MediaItem:

[Sitecore.Data.Items.MediaItem]$item = Get-Item master: -Query $query | Where-Object { $_.TemplateName -eq $TemplateName } | Select -First 1

Voici le script complet pour le transfert de tous les fichiers.

function Update-MediaItem {
    [CmdletBinding()]
    param(
        [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$filePath,

        [Parameter(Position=1, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$mediaPath)
		
	$itemMedia = Get-Item -Path "master:$mediaPath"
	$itemMedia.Editing.BeginEdit()
	$itemMedia.Fields['File Path'].Value = ""
	if ($itemMedia.Fields['Alt']) {
		$itemMedia.Fields['Alt'].Value = $itemMedia.Name
	}
	$itemMedia.Editing.EndEdit()

    [Sitecore.Data.Items.MediaItem]$item = gi -Path "master:$mediaPath"
	[Sitecore.Resources.Media.Media] $media = [Sitecore.Resources.Media.MediaManager]::GetMedia($item);
    $extension = [System.IO.Path]::GetExtension($filePath);
	$extension = $extension.Substring(1);
	$stream = New-Object -TypeName System.IO.FileStream -ArgumentList $filePath, "Open", "Read"
    $media.SetStream($stream, $extension);
    $stream.Close();
}

function Find-MediaItem {
    [CmdletBinding()]
    param(
        [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$fullName,
		
		[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$extension
		)
        
	$mediaName = [io.path]::GetFileNameWithoutExtension($fullName)
	$uploadPosition = $fullName.IndexOf("App_Data\upload\")
	$SitecorePath = $fullName.Substring($uploadPosition + 16)
	$mediaNamePosition = $SitecorePath.IndexOf($mediaName)
	$SitecorePath = $SitecorePath.Substring(0, $mediaNamePosition)
	$SitecorePath = "#" + $SitecorePath.replace("\", "#/#")
	if ($SitecorePath.EndsWith("/#")) {
		$SitecorePath = $SitecorePath.Substring(0, $SitecorePath.Length - 2)
	} else {
		$SitecorePath = $SitecorePath + "#"
	}
	$query = "/sitecore/media library//{0}//*[@@name='{1}']" -f $SitecorePath, $mediaName
	Write-Host $query
	$TemplateName = $extension
	if ($extension -eq "pdf") {
		$TemplateName = "Pdf"
	} elseif ($extension -eq "jpg") {
		$TemplateName = "Jpeg"
	} elseif ($extension -eq "jpeg") {
		$TemplateName = "Jpeg"
	} elseif ($extension -eq "png") {
		$TemplateName = "Image"
	} elseif ($extension -eq "svg") {
		$TemplateName = "Image"
	} elseif ($extension -eq "mp3") {
		$TemplateName = "Mp3"
	}
	[Sitecore.Data.Items.MediaItem]$item = Get-Item master: -Query $query | Where-Object { $_.TemplateName -eq $TemplateName } | Select -First 1
	if ($item.ID -eq "") {
		$SitecorePath = $SitecorePath.replace(" ", "")
		$mediaName = $mediaName.replace(" - ", "-")
		$mediaName = $mediaName.replace(" ", "-")
		$query = "/sitecore/media library//{0}//*[@@name='{1}']" -f $SitecorePath, $mediaName
		[Sitecore.Data.Items.MediaItem]$item = Get-Item master: -Query $query | Where-Object { $_.TemplateName -eq $TemplateName } | Select -First 1
	}
	return $item
}

$ImageFileRegEx = '.jpg|.png|.pdf|.jpeg|.svg|.mp3'
Get-ChildItem -Path "$SitecoreDataFolder\upload\" -Recurse | Where-Object -FilterScript {$_.Name -match $ImageFileRegEx} | ForEach-Object {
	$file = $_;
	$extension = [System.IO.Path]::GetExtension($file.FullName);
	$extension = $extension.Substring(1).ToLower();
	$mediaItem = Find-MediaItem $file.FullName $extension
	$mediaPath = "{0}{1}" -f $([Sitecore.Constants]::MediaLibraryPath), $mediaItem.MediaPath
	$mediaId = "{0}" -f $mediaItem.ID
	if ($mediaId -ne "") {
		Write-Host $mediaId $mediaPath
		try {
			Update-MediaItem $file.FullName $mediaPath
			Remove-Item $file.FullName
			Write-Host "Imported and deleted"
		} catch {
			Write-Host "Something went wrong"
		}
	} else {
		Write-Host "Not Found $file.BaseName $extension"
	}
}

Update-MediaItem est la fonction permettant de joindre un fichier à un élément multimédia Sitecore.

Find-MediaItem est la fonction de recherche d’un élément multimédia Sitecore en fonction du nom de fichier. Nous construisons une requête basée sur le chemin du nom de fichier et le modèle basé sur l’extension de fichier. Si le premier Get-Item ne renvoie rien, nous faisons un autre essai avec un certain nettoyage du nom de fichier.

La fonction principale parcourt chaque fichier dans upload/ en utilisant Get-ChildItem. Pour chaque fichier, nous essayons de rechercher l’élément Sitecore correspondant (Find-MediaItem). Si nous avons un élément, nous téléchargeons le fichier vers cet élément et supprimons le fichier du dossier (Update-MediaItem et Remove-Item).

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

%d bloggers like this: