Comment contourner la restriction du navigateur et joindre deux fichiers ou plus à la fois: pièce jointe multi-fichier

Bonjour, Habr!



Résolvons un problème non trivial. Imaginez que vous ayez besoin de télécharger des données via l'interface de manière élémentaire, par exemple, cliquez sur le bouton "Télécharger les fichiers".



Prenons le Chrome v.88 par défaut. La tâche ressemble à ceci:



  • Générez des fichiers côté client.
  • Téléchargez tous les fichiers générés en un seul clic.


Cela peut être n'importe quoi: un tas de binaires, de grandes archives avec des sauvegardes, une galerie d'images, etc. Nous parlerons spécifiquement du mécanisme de téléchargement en tant que tel, nous prendrons donc le téléchargement de texte et d'images comme exemple.





Bien sûr, vous pouvez résoudre ce problème en compressant simplement tous les fichiers nécessaires dans une archive ZIP, puis en la téléchargeant. Il s'avère que l'utilisateur télécharge un seul fichier, qu'il décompresse ensuite lui-même. Par exemple, vous pouvez utiliser la bibliothèque jszip , qui vous permet de télécharger un ensemble de fichiers en les compressant.



Voici un petit exemple de téléchargement précompressé à partir de la documentation:



var zip = new JSZip();
zip.file("Hello.txt", "Hello World\n");
var img = zip.folder("images");
img.file("smile.gif", imgData, {base64: true}); zip.generateAsync({type:"blob"}).then(function(content) {
// see FileSaver.js
saveAs(content, "example.zip"); });
      
      





"Où est la non-trivialité ici?" - tu demandes. Et vous aurez raison. Et si on parle du téléchargement simultané de deux, trois ou dix fichiers depuis le site? Par exemple: il y a une liste dans la sélection, où vous pouvez sélectionner un certain nombre de fichiers à télécharger. Introduisons une condition supplémentaire: l'utilisateur n'a pas d'archiveur installé, nous rejetons donc l'option avec compression dans l'archive. Comment résoudre ce problème?



Tout d'abord, préparons le navigateur. Chrome interdit le téléchargement de fichiers multiples par défaut. C'est pour des raisons de sécurité. Par conséquent, cette fonction doit d'abord être déverrouillée dans les paramètres du navigateur:



  1. Nous allons dans les paramètres du site: chrome: // paramètres / contenu.
  2. Accédez aux autorisations supplémentaires.
  3. Choisissez Téléchargements automatiques.
  4. Ajoutez le site requis à la catégorie Autoriser.








Génial, maintenant votre navigateur est devenu moins sécurisé et vous permet de télécharger plusieurs fichiers sur un site particulier à la fois.



Approche n ° 1 - FileReader



Examinons la première approche en utilisant l'exemple de génération de fichiers à l'aide de FileReader et de l'API de lecture base64. Je note tout de suite que FileReader dispose d'une API assez étendue, alors choisissez ce que vous préférez: text, arrayBuffer ou binaryString.



(function () {
  const button = document.getElementById("download_with_reader");
  const content = ["content-1", "content-2", "content-3"];
    const createLink = () => {
    let link = document.createElement('a');
    link.download = 'hello.txt';
    return link;
  }
    const generateBlob = () => {
    for (const [index, value] of content.entries()) {
      const blob = new Blob([value], { type: "text/plain" });
      download(blob, index);
    }
  }
  const download = (blob, index) => {
    const link = createLink();
    let reader = new FileReader();
    reader.readAsDataURL(blob);
    reader.onload = function () {
      link.href = reader.result;
      link.download = `content-${index+1}.txt`;
      link.click();
    }
  }
    button.addEventListener("click", generateBlob);
}) ();

      
      





[code sur Gitlab]



Approche n ° 2 - createObjectURL



Vous pouvez également utiliser createObjectURL - il vous permet de stocker des objets File ou Blobs.



(function () {
  const button = document.getElementById("download_with_url_object");
  const content = ["content-1", "content-2", "content-3"];
  
  const createLink = () => {
    let link = document.createElement('a');
    link.download = 'hello.txt';
    return link;
  }
  const generateBlob = () => {
    for (const [index, value] of content.entries()) {
      const blob = new Blob([value], { type: "text/plain" });
      download(blob, index);
    }
  }
  const download = (blob, index) => {
    const link = createLink();
    link.href = URL.createObjectURL(blob);
    link.download = `content-${index+1}.txt`;
    link.click();
    URL.revokeObjectURL(link.href);
  }
   button.addEventListener("click", generateBlob);
}) ();

      
      





[code sur Gitlab]



Approche n ° 3 - Télécharger à partir de l'URL



Les deux options ci-dessus génèrent des fichiers côté client. Bien sûr, ce ne sera pas toujours le cas, de temps en temps, nous recevons des fichiers du backend via des liens directs. Cela peut être fait en téléchargeant à partir d'une URL. Chrome nécessite une latence, la mise en œuvre de la latence artificielle deviendra donc une fonctionnalité de cette méthode.



(function () {
(function () {
  const button = document.getElementById("download_with_request");
  const urls = ["images/image-1.jpg", "images/image-2.jpg", "images/image-3.jpg"];
  
  const delay = () => new Promise(resolve => setTimeout(resolve, 1000));
  
  const downloadWithRequest = async () => {
    for await (const [index, url] of urls.entries()) {
      await delay();
      const link = document.createElement("a");
      link.href = url;
      link.download = `image-${index+1}`;
      link.click();
    }
  }
  
  button.addEventListener("click", downloadWithRequest);
}) ();


      
      





[code sur Gitlab]



Total



Voici trois façons assez simples de télécharger plusieurs fichiers à partir d'un site en même temps et de le faire rapidement. L'essentiel est d'activer les autorisations nécessaires pour un site spécifique, puis de choisir la méthode que vous aimez.



All Articles