Cómo evitar la restricción del navegador y adjuntar dos o más archivos a la vez: archivo adjunto de varios archivos

¡Hola, Habr!



Resolvamos un problema no trivial. Imagine que necesita descargar datos a través de la interfaz de forma elemental, por ejemplo, haga clic en el botón "Descargar archivos".



Tomemos el Chrome v.88 predeterminado. La tarea suena así:



  • Genere archivos del lado del cliente.
  • Descarga todos los archivos generados con un solo clic.


Puede ser cualquier cosa: un montón de archivos binarios, archivos grandes con copias de seguridad, una galería de imágenes, etc. Hablaremos específicamente del mecanismo de descarga como tal, por lo que tomaremos como ejemplo la descarga de texto e imágenes.





Por supuesto, puede resolver este problema simplemente comprimiendo todos los archivos necesarios en un archivo ZIP y luego descargándolo. Resulta que el usuario descarga un solo archivo, que luego descomprime por su cuenta. Por ejemplo, puede usar la biblioteca jszip , que le permite descargar un conjunto de archivos comprimiéndolos.



Aquí hay un pequeño ejemplo de una descarga precomprimida de los documentos:



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"); });
      
      





"¿Dónde está la no trivialidad aquí?" - usted pregunta. Y tendrás razón. ¿Y si hablamos de la descarga simultánea de dos, tres o diez archivos del sitio? Por ejemplo: hay una lista en la selección, donde puede seleccionar una cierta cantidad de archivos para descargar. Introduzcamos una condición adicional: el usuario no tiene un archivador instalado, por lo que descartamos la opción con compresión al archivo. ¿Cómo resolver este problema?



Primero, preparemos el navegador. Chrome prohíbe la descarga de archivos múltiples de forma predeterminada. Esto es por razones de seguridad. Por lo tanto, esta función debe desbloquearse primero en la configuración del navegador:



  1. Vamos a la configuración del sitio: chrome: // settings / content.
  2. Vaya a Permisos adicionales.
  3. Elija Descargas automáticas.
  4. Agregue el sitio requerido a la categoría Permitir.








Genial, ahora su navegador se ha vuelto menos seguro y le permite descargar varios archivos en un sitio en particular a la vez.



Enfoque n. ° 1 - FileReader



Veamos el primer enfoque usando el ejemplo de generación de archivos usando FileReader y la API de lectura base64. Noto de inmediato que FileReader tiene una API bastante extensa, así que elija lo que más le guste: text, arrayBuffer o 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);
}) ();

      
      





[código en Gitlab]



Enfoque # 2 - createObjectURL



También puede usar createObjectURL: le permite almacenar objetos de archivo o 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);
}) ();

      
      





[código en Gitlab]



Enfoque n. ° 3: descargar desde la URL



Las dos opciones anteriores generan archivos del lado del cliente. Por supuesto, este no siempre será el caso, de vez en cuando recibimos archivos del backend a través de enlaces directos. Esto se puede hacer descargándolo desde una URL. Chrome requiere latencia, por lo que la implementación de latencia artificial se convertirá en una característica de este método.



(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);
}) ();


      
      





[código en Gitlab]



Total



Aquí hay tres formas bastante simples de descargar varios archivos de un sitio al mismo tiempo y hacerlo rápidamente. Lo principal es activar los permisos necesarios para un sitio específico y luego elegir el método que desee.



All Articles