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,ContentDocumentIdFROM ContentDocumentLinkWHERE LinkedEntityId IN:votreVariableORDER 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,LastModifiedDateFROM ContentVersionwhere ContentDocumentId IN:setContentDocumentOfRecordSet
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}) ;
- 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 zipsaveAs(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 !