Jour 9 : Export de fichiers en zip depuis des list view grâce aux LWC

Par 

6 minutes de lecture
Salesforce Release Notes

On se retrouve aujourd’hui pour le 9e jour de ce calendrier de l’avent Texei. Vous avez pu lire hier, l’article de Maryem sur comment organiser une rétrospective en fin d’année. Dans cet article, nous allons voir différentes méthodes pour pouvoir exporter les fichiers liés à un enregistrement dans un fichier zip grâce aux LWC.
En préambule de cet article, je vous invite à lire l’article de Mouloud concernant l’édition en masse d’une list view via un flow, ici.

  •  Static ressources

Tout d’abord, j’ai dû récupérer deux libraires javascript que vous retrouvez ici :

La première, JSZIP permet de générer un fichier zip et puis, FileSaver m’a permis de lancer le téléchargement du zip que je venais de créer.

Dans un second temps, il vous faut convertir les libraires récupérées en fichier zip pour pouvoir les ajouter aux static resources de votre org.

  • Configuration et utilisation dans le lightning web component

    • Import des librairies

Il vous faut tout d’abord, importer les libraires ajoutées aux ressources statiques dans l’étape précédente.

Mes deux ressources se nomment jsziplib et filesaver que vous retrouvez en fin de ligne.

import jszip from ‘@salesforce/resourceUrl/jsziplib‘;
import filesaver from ‘@salesforce/resourceUrl/filesaver‘;

    • Création d’un object personnalisé dans une classe

Cette étape n’est normalement pas nécessaire, mais à l’utilisation je me suis rendu compte que lorsque l’on récupère le champ VersionData côté LWC, on obtient une chaîne de caractères de type « BLOB [21511 bytes] » et non pas le contenu du fichier.

J’ai donc créé une classe imbriquée, dans une autre classe pour pouvoir forcer le base64Encode. Évidemment, je l’ai déclaré de cette façon, mais vous pouvez le faire comme vous voulez à partir du moment où le champ VersionData passe par un base64Encode.

public class customContentVersion {
@AuraEnabled
public Id ContentVersionId {get;set;}
@AuraEnabled
public String base64Content{get;set;}
@AuraEnabled
public String fileName{get;set;}
}
public static String base64Encode(Blob versionData) {
        return EncodingUtil.base64Encode(versionData);
}
    • Requêtes de récupération des fichiers

Une fois ceci mit en place nous avons besoin de requêtes SOQL pour récupérer les enregistrements.

Dans notre cas, nous devons récupérer des enregistrements de type ContentVersion, mais nous avons à notre disposition que les Ids des enregistrements sélectionnés dans la list view et il n’existe pas de lien direct entre l’objet choisi et les enregistrements de ContentVersion. Il nous faut donc, dans un premier temps passer par l’objet ContentDocumentLink.

Tout d’abord, voici un exemple de requêtes sur les ContentDocumentLink :

SELECT Id,
ContentDocumentId
FROM ContentDocumentLink
WHERE LinkedEntityId IN:votreVariable
ORDER BY LinkedEntityId ASC])

Dans un second temps, il faut effectuer la requête sur ContentVersion avec les Ids précédemment récupérés :

SELECT ID,
ContentDocumentId,
IsLatest,
Origin,
PublishStatus,
Title,
VersionNumber,
FileExtension,
ContentModifiedDate,
PathOnClient,
FileType,
VersionData,
LastModifiedDate
FROM ContentVersion
where ContentDocumentId IN:setContentDocumentOfRecordSet
Ces deux requêtes sont des exemples, vous pouvez évidemment décider des champs à sélectionner.
Pour connaître les champs disponibles dans les deux objets, je vous ajoute le lien vers la documentation Salesforce

Et pour finir cette étape, le résultat de cette dernière requête, m’a permis de construire une liste de customContentVersion, l’objet créé à l’étape du dessus.

    • Initialisation des libraires

Après avoir importé les libraires dans mon composant, il a fallu initialiser les libraires pour qu’elles soient utilisables dans mon code.

En utilisant le promise, cela me garantit que mes scripts sont chargés avant d’exécuter mes propres lignes de code écrites dans ma méthode doExport.

Promise.all([
loadScript(this, jszip + ‘/jszip.js’),
loadScript(this, filesaver + ‘/filesaver.js’)
])
.then(() => {
console.log(‘LIB LOADED’);
this.doExport();
})
.catch(error => {
this.dispatchEvent(
new ShowToastEvent({
title: ‘Error loading js library’,
message: ‘error : ‘ + error,
variant: ‘error’
})
);

});

    • Création et téléchargement du fichier zip

Maintenant que nous sommes sûrs d’avoir tous les éléments à notre disposition, nous allons pouvoir construire notre fichier Zip à notre convenance.

Tout d’abord, voyons comment on initialise notre contenant.

    • Initialisation de l’objet JS

Nous voilà donc dans la première étape de notre méthode doExport. Après m’être garanti d’avoir des fichiers en résultat de ma requête, j’ai pu instancier mon objet qui sera le receptacle de tout nos enregistrements remontés. Voici comment faire :

const zip = new JSZip();
    • Ajout du fichier dans le zip

Ensuite, dans une boucle qui nous permet de parcourir tous nos fichiers à ajouter, j’ai pu construire le nom du fichier à intégrer et non pas celui du zip final. On aurait également pu utiliser le champ PathOnClient de l’objet ContentVersion qui contient le nom complet (nom + extension) du fichier qui serait contenu dans notre exemple dans le champ fileName de notre objet custom.

Une fois notre contenu prêt à être additionné au fichier zip, nous pouvons l’insérer de la sorte :

zip.file(fileName, result[i].base64Content, {base64:true}) ;
Dans mon cas :
  • fileName est une variable construite dans mon itération.
  • result contient ma liste d’objet custom dans lequel on accède à l’attribut base64Content (le contenu du fichier).
  • {base64:true} est une option de la méthode file.
    • Génération du fichier et téléchargement

Et pour finir la dernière étape !

Une fois notre zip bien rempli, nous allons devoir le générer ! Comment me diriez-vous ?!

Ceci est très simple, il nous suffit d’appeler la méthode generateAsync comme ci-dessous :

zip.generateAsync({type: »blob »}, function updateCallback(metadata) {
})
.then(function callback(blob) {
// Déclenche le téléchargement du zip
saveAs(blob, zipName + « .zip »);
}, function (e) {
console.log(‘ERROR CREATING ZIP : ‘ + e);
});

Essayons de comprendre les différents éléments dans ce bout de code.

Encore une fois, nous devons définir quel type de données nous utilisons, ici un blob. Si vous ne savez pas ce qu’est un blob, voici le lien vers la page Wikipédia : ici.

Pour finir, une fois que la génération du zip prête, nous pouvons lancer le téléchargement et ceci grâce à notre libraire fileSaver et sa méthode saveAs qui demande 2 paramètres, le premier le contenu du fichier donc notre blob et son nom.

En conclusion, vous pouvez demander pourquoi je n’ai pas utilisé l’url pour pouvoir télécharger des pièces jointes (‘/sfsites/c/sfc/servlet.shepherd/document/download/’ + ID). La réponse est simple car je ne pouvais pas avoir la main ni sur le nom du fichier, ni sur l’arborescence au sein du zip.

J’espère que cet article vous a plu, et   en attendant lundi pour celui de Paul.

Bonnes fêtes à tous !

A lire également sur le blog

Copado

Introduction à Copado

Vous aimeriez avoir une idée de ce qu’est Copado, savoir ce qu’apporte l’outil et le tester éventuellement ? Peut-être souhaiteriez-vous aussi connaître les étapes pour se former dessus ? …
avril 2024
Conseils
Interview-Romain-Quijal-Texeï

Portrait de Texiens : Romain Quijal, Développeur chez Texeï

👋 Découvrez le portrait de Romain Quijal, Développeur chez Texeï ! 🚀 Arrivé il y a un peu plus d’un an chez Texeï, Romain une étoile montante dans l’univers …
avril 2024
Interviews

Comment utiliser le pré-header ?

Comment utiliser le pré-header ? Dans le paysage en constante évolution du marketing numérique, la création d’emails captivants est devenue un véritable art. Chaque élément joue un rôle crucial …
mars 2024
Conseils
Avantages de Salesforce pour les PME

Pourquoi faire de la conduite du changement ? 

D’abord, qu’est-ce que la conduite du changement ? La conduite du changement (aussi appelée change management ou change) sert à accompagner les différentes parties prenantes lors d’une transformation dans …
mars 2024
Conseils
Interview-zoe-texei-1

Portrait de Texiens : Zoé Cadiou, Responsable Marketing Opérationnel

👋 Découvrez le portrait de Zoé Cadiou, Responsable Marketing Opérationnel chez Texeï ! 🚀 Arrivée chez Texeï en tant que Responsable de Communication, Zoé endosse désormais la casquette de Responsable …
février 2024
Interviews
Virgile-Paré-portrait -de-texien

Portrait de Texiens : Virgile Paré, Senior Business Analyst

👋 A l’honneur dans notre portrait de texiens, Virgile Paré, Senior Business Analyst, Spécialiste CRM-Analytics, et Manager chez Texeï ! 🚀 Arrivé il y a deux ans maintenant, Virgile …
février 2024
Interviews