Descarga varios archivos con una sola acción

109

No estoy seguro de si esto es posible utilizando tecnologías web estándar.

Quiero que el usuario pueda descargar varios archivos en una sola acción. Es decir, haga clic en las casillas de verificación junto a los archivos y luego obtenga todos los archivos que se marcaron.

¿Es posible? Si es así, ¿qué estrategia básica recomienda? Sé que puedo usar la tecnología de cometas para crear eventos del lado del servidor que desencadenan una HttpResponse, pero espero que haya una forma más sencilla.

Ankur
fuente

Respuestas:

60

HTTP no admite la descarga de más de un archivo a la vez.

Hay dos soluciones:

  • Abra x cantidad de ventanas para iniciar la descarga de archivos (esto se haría con JavaScript)
  • solución preferida crear un script para comprimir los archivos
Jacob Relkin
fuente
39
¿Por qué un archivo zip es la solución preferida ? Crea un paso adicional para el usuario (descomprimir).
Speedplane
7
Esta página contiene javascript que crea un archivo ZIP. Mira la página, tiene un gran ejemplo. stuk.github.io/jszip
Netsi1964
Una tercera forma es encapsular los archivos en un archivo SVG. Si los archivos se muestran en el navegador, el SVG parece ser la mejor manera.
VectorVortec
4
El propio HTTP admite el formato de mensaje de varias partes. Pero los navegadores no analizan de forma portátil las respuestas de varias partes desde el lado del servidor, pero técnicamente no hay nada difícil en hacer esto.
CMCDragonkai
2
Esta puede ser una excelente solución con javascript github.com/sindresorhus/multi-download
juananruiz
84

var links = [
  'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.exe',
  'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.dmg',
  'https://s3.amazonaws.com/Minecraft.Download/launcher/Minecraft.jar'
];

function downloadAll(urls) {
  var link = document.createElement('a');

  link.setAttribute('download', null);
  link.style.display = 'none';

  document.body.appendChild(link);

  for (var i = 0; i < urls.length; i++) {
    link.setAttribute('href', urls[i]);
    link.click();
  }

  document.body.removeChild(link);
}
<button onclick="downloadAll(window.links)">Test me!</button>

Matěj Pokorný
fuente
3
Estoy trabajando con muchos tipos de archivos, incluidas imágenes, y esto funcionó mejor para mí. Sin embargo, link.setAttribute('download', null);renombré todos mis archivos a nulos.
tehlivi
7
No funciona en IE 11, solo descarga el .jar (último elemento de la lista) fue la solución perfecta :(
Immutable Brick
1
@AngeloMoreira Sí, al menos funciona en Edge. Si intenta descargar varios archivos en IE en sitios de MS, por ejemplo , generan múltiples ventanas emergentes, así que creo que la mejor solución para IE sigue siendo de Dmitry Nogin arriba .
Matěj Pokorný
1
@tehlivi - Encontré lo mismo. Agrega el link.setAttribute('download',filename)interior del bucle. Esto le permite nombrar los archivos como desee. Además, creo que solo debe ser el nombre del archivo sin incluir la URL. Terminé enviando dos matrices: una con la URL completa y otra con solo el nombre del archivo.
PhilMDev
7
No funciona correctamente en Chrome v75, Windows 10: el único archivo que se descarga es Minecraft.jar.
andreivictor
54

Puede crear un conjunto temporal de iframes ocultos, iniciar la descarga mediante GET o POST dentro de ellos, esperar a que comiencen las descargas y eliminar iframes:

<!DOCTYPE HTML>
<html>
<body>
  <button id="download">Download</button> 

  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
  <script type="text/javascript">

     $('#download').click(function() {
       download('http://nogin.info/cv.doc','http://nogin.info/cv.doc');
     });

     var download = function() {
       for(var i=0; i<arguments.length; i++) {
         var iframe = $('<iframe style="visibility: collapse;"></iframe>');
         $('body').append(iframe);
         var content = iframe[0].contentDocument;
         var form = '<form action="' + arguments[i] + '" method="GET"></form>';
         content.write(form);
         $('form', content).submit();
         setTimeout((function(iframe) {
           return function() { 
             iframe.remove(); 
           }
         })(iframe), 2000);
       }
     }      

  </script>
</body>
</html>

O, sin jQuery:

 function download(...urls) {
    urls.forEach(url => {
      let iframe = document.createElement('iframe');
      iframe.style.visibility = 'collapse';
      document.body.append(iframe);

      iframe.contentDocument.write(
        `<form action="${url.replace(/\"/g, '"')}" method="GET"></form>`
      );
      iframe.contentDocument.forms[0].submit();

      setTimeout(() => iframe.remove(), 2000);
    });
  }
Dmitry Nogin
fuente
impresionante, pero por algunas razones los archivos no se descargan. Para mí, la razón parece que la página se recarga después de que se ejecuta el script, parece ser la razón por la que los archivos no se descargan. ¿Alguna pista de lo que estoy haciendo mal?
Chirag Mehta
Tengo varios problemas con esta solución. En IE, dado que mi ventana principal ha cambiado el dominio de documento, tengo un acceso denegado. Hay varias publicaciones sobre cómo solucionar este problema, pero todas se sienten hack. En Chrome, el usuario recibe un mensaje de advertencia que le indica que el sitio web intenta descargar varios archivos (pero al menos funciona). En Firefox, obtengo un cuadro de descarga diferente, pero cuando hago clic en Guardar, no obtengo el cuadro de diálogo para guardar archivo ...
Melanie
Esto no funcionó para mí, porque el cuadro de diálogo del archivo "bloquea" que aparezcan los otros cuadros de diálogo de guardado. Lo que hice fue algo un poco hacky: la acción mousemove se registra solo después de que desaparece el cuadro de diálogo del archivo, así que lo usé, pero no está probado. Lo agregaré como otra respuesta.
Karel Bílek
2
¿Funciona esto en IE10? Recibo: El objeto no admite la propiedad o el método 'escribir'
Hoppe
por qué la función de regresar (cierre?) en setTimeout()?
robisrob
34

Esta solución funciona en todos los navegadores y no genera advertencias. En lugar de crear un iframe, aquí creamos un enlace para cada archivo. Esto evita que aparezcan mensajes de advertencia.

Para manejar la parte de bucle, usamos setTimeout, que es necesario para que funcione en IE.

/**
 * Download a list of files.
 * @author speedplane
 */
function download_files(files) {
  function download_next(i) {
    if (i >= files.length) {
      return;
    }
    var a = document.createElement('a');
    a.href = files[i].download;
    a.target = '_parent';
    // Use a.download if available, it prevents plugins from opening.
    if ('download' in a) {
      a.download = files[i].filename;
    }
    // Add a to the doc for click to work.
    (document.body || document.documentElement).appendChild(a);
    if (a.click) {
      a.click(); // The click method is supported by most browsers.
    } else {
      $(a).click(); // Backup using jquery
    }
    // Delete the temporary link.
    a.parentNode.removeChild(a);
    // Download the next file with a small timeout. The timeout is necessary
    // for IE, which will otherwise only download the first file.
    setTimeout(function() {
      download_next(i + 1);
    }, 500);
  }
  // Initiate the first download.
  download_next(0);
}
<script>
  // Here's a live example that downloads three test text files:
  function do_dl() {
    download_files([
      { download: "http://www.nt.az/reg.txt", filename: "regs.txt" },
      { download: "https://www.w3.org/TR/PNG/iso_8859-1.txt", filename: "standards.txt" },
      { download: "http://qiime.org/_static/Examples/File_Formats/Example_Mapping_File.txt", filename: "example.txt" },
    ]);
  };
</script>
<button onclick="do_dl();">Test downloading 3 text files.</button>

avión de velocidad
fuente
Este es el único aquí que funcionó para mí, ya que tengo que admitir IE. Gracias.
Øystein Amundsen
1
Esta respuesta es de oro. Solo uno que funciona en todos los navegadores sin un mensaje de advertencia. Especialmente IE. Cosas brillantes
Mukul Goel
No funciona en Chrome OSX, me pide que permita múltiples descargas, pero incluso si lo hago, solo se descarga el primer archivo y escuché una cantidad de "bip" correspondiente a la cantidad de archivos que quedan por descargar
Allan Raquin
2
El botón no hace nada Google Chrome Version 76.0.3809.100 (Official Build) (64-bit).
1934286
1
El botón no funciona en el desbordamiento de la pila Ejecute el fragmento de código. Browser Crome @speedplane
mb
5

La forma más sencilla sería servir los múltiples archivos agrupados en un archivo ZIP.

Supongo que podría iniciar múltiples descargas de archivos usando un montón de iframes o ventanas emergentes, pero desde el punto de vista de la usabilidad, un archivo ZIP es aún mejor. ¿Quién quiere hacer clic en diez cuadros de diálogo "Guardar como" que mostrará el navegador?

Thilo
fuente
3
Me doy cuenta de que su respuesta es de 2010, pero muchos usuarios navegan con teléfonos inteligentes en la actualidad, algunos de los cuales no pueden abrir las cremalleras de forma predeterminada (un amigo me dice que su Samsung S4 Active no puede abrir las cremalleras).
Hydraxan14
4

Estoy de acuerdo en que un archivo zip es una solución más ordenada ... Pero si tiene que enviar varios archivos, esta es la solución que se me ocurrió. Funciona en IE 9 y versiones posteriores (posiblemente una versión inferior también, no lo he probado), Firefox, Safari y Chrome. Chrome mostrará un mensaje al usuario para obtener su consentimiento para descargar varios archivos la primera vez que su sitio lo use.

function deleteIframe (iframe) {
    iframe.remove(); 
}
function createIFrame (fileURL) {
    var iframe = $('<iframe style="display:none"></iframe>');
    iframe[0].src= fileURL;
    $('body').append(iframe);
    timeout(deleteIframe, 60000, iframe);             
 }
 // This function allows to pass parameters to the function in a timeout that are 
 // frozen and that works in IE9
 function timeout(func, time) {
      var args = [];
      if (arguments.length >2) {
           args = Array.prototype.slice.call(arguments, 2);
      }
      return setTimeout(function(){ return func.apply(null, args); }, time);
 }
 // IE will process only the first one if we put no delay
 var wait = (isIE ? 1000 : 0);
 for (var i = 0; i < files.length; i++) {  
      timeout(createIFrame, wait*i, files[i]);
 }

El único efecto secundario de esta técnica es que el usuario verá un retraso entre el envío y el cuadro de diálogo de descarga. Para minimizar este efecto, le sugiero que utilice la técnica que se describe aquí y en esta pregunta Detectar cuando el navegador recibe la descarga de un archivo que consiste en establecer una cookie con su archivo para saber que ha comenzado la descarga. Deberá verificar esta cookie en el lado del cliente y enviarla en el lado del servidor. No olvide establecer la ruta adecuada para su cookie o es posible que no la vea. También deberá adaptar la solución para la descarga de varios archivos.

Melanie
fuente
4

Una versión jQuery del iframe responde:

function download(files) {
    $.each(files, function(key, value) {
        $('<iframe></iframe>')
            .hide()
            .attr('src', value)
            .appendTo($('body'))
            .load(function() {
                var that = this;
                setTimeout(function() {
                    $(that).remove();
                }, 100);
            });
    });
}
Yirmiyahu Fischer
fuente
Cada uno busca una matriz. Esto funcionará: download(['http://nogin.info/cv.doc','http://nogin.info/cv.doc']);Sin embargo, esto no funciona para descargar archivos de imagen.
tehlivi
3

Solución angular:

HTML

    <!doctype html>
    <html ng-app='app'>
        <head>
            <title>
            </title>
            <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
            <link rel="stylesheet" href="style.css">
        </head>
        <body ng-cloack>        
            <div class="container" ng-controller='FirstCtrl'>           
              <table class="table table-bordered table-downloads">
                <thead>
                  <tr>
                    <th>Select</th>
                    <th>File name</th>
                    <th>Downloads</th>
                  </tr>
                </thead>
                <tbody>
                  <tr ng-repeat = 'tableData in tableDatas'>
                    <td>
                        <div class="checkbox">
                          <input type="checkbox" name="{{tableData.name}}" id="{{tableData.name}}" value="{{tableData.name}}" ng-model= 'tableData.checked' ng-change="selected()">
                        </div>
                    </td>
                    <td>{{tableData.fileName}}</td>
                    <td>
                        <a target="_self" id="download-{{tableData.name}}" ng-href="{{tableData.filePath}}" class="btn btn-success pull-right downloadable" download>download</a>
                    </td>
                  </tr>              
                </tbody>
              </table>
                <a class="btn btn-success pull-right" ng-click='downloadAll()'>download selected</a>

                <p>{{selectedone}}</p>
            </div>
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
            <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
            <script src="script.js"></script>
        </body>
    </html>

app.js

var app = angular.module('app', []);            
app.controller('FirstCtrl', ['$scope','$http', '$filter', function($scope, $http, $filter){

$scope.tableDatas = [
    {name: 'value1', fileName:'file1', filePath: 'data/file1.txt', selected: true},
    {name: 'value2', fileName:'file2', filePath: 'data/file2.txt', selected: true},
    {name: 'value3', fileName:'file3', filePath: 'data/file3.txt', selected: false},
    {name: 'value4', fileName:'file4', filePath: 'data/file4.txt', selected: true},
    {name: 'value5', fileName:'file5', filePath: 'data/file5.txt', selected: true},
    {name: 'value6', fileName:'file6', filePath: 'data/file6.txt', selected: false},
  ];  
$scope.application = [];   

$scope.selected = function() {
    $scope.application = $filter('filter')($scope.tableDatas, {
      checked: true
    });
}

$scope.downloadAll = function(){
    $scope.selectedone = [];     
    angular.forEach($scope.application,function(val){
       $scope.selectedone.push(val.name);
       $scope.id = val.name;        
       angular.element('#'+val.name).closest('tr').find('.downloadable')[0].click();
    });
}         


}]);

ejemplo de trabajo: https://plnkr.co/edit/XynXRS7c742JPfCA3IpE?p=preview

seguro
fuente
1

Para mejorar la respuesta de @Dmitry Nogin: esto funcionó en mi caso.

Sin embargo, no se ha probado, ya que no estoy seguro de cómo funciona el diálogo del archivo en varias combinaciones de sistema operativo / navegador. (Por lo tanto, wiki de la comunidad).

<script>
$('#download').click(function () {
    download(['http://www.arcelormittal.com/ostrava/doc/cv.doc', 
              'http://www.arcelormittal.com/ostrava/doc/cv.doc']);
});

var download = function (ar) {
    var prevfun=function(){};
    ar.forEach(function(address) {  
        var pp=prevfun;
        var fun=function() {
                var iframe = $('<iframe style="visibility: collapse;"></iframe>');
                $('body').append(iframe);
                var content = iframe[0].contentDocument;
                var form = '<form action="' + address + '" method="POST"></form>';
                content.write(form);
                $(form).submit();
                setTimeout(function() {    
                    $(document).one('mousemove', function() { //<--slightly hacky!
                        iframe.remove();
                        pp();
                    });
                },2000);
        }
        prevfun=fun; 
      });
      prevfun();   
}
</script>
Karel Bílek
fuente
1

Esto funciona en todos los navegadores (IE11, firefox, Edge, Chrome y Chrome Mobile). Mis documentos están en varios elementos seleccionados. Los navegadores parecen tener problemas cuando intentas hacerlo demasiado rápido ... Así que utilicé un tiempo de espera.

//user clicks a download button to download all selected documents
$('#downloadDocumentsButton').click(function () {
    var interval = 1000;
    //select elements have class name of "document"
    $('.document').each(function (index, element) {
        var doc = $(element).val();
        if (doc) {
            setTimeout(function () {
                window.location = doc;
            }, interval * (index + 1));
        }
    });
});

Esta es una solución que usa promesas:

 function downloadDocs(docs) {
        docs[0].then(function (result) {
            if (result.web) {
                window.open(result.doc);
            }
            else {
                window.location = result.doc;
            }
            if (docs.length > 1) {
                setTimeout(function () { return downloadDocs(docs.slice(1)); }, 2000);
            }
        });
    }

 $('#downloadDocumentsButton').click(function () {
        var files = [];
        $('.document').each(function (index, element) {
            var doc = $(element).val();
            var ext = doc.split('.')[doc.split('.').length - 1];

            if (doc && $.inArray(ext, docTypes) > -1) {
                files.unshift(Promise.resolve({ doc: doc, web: false }));
            }
            else if (doc && ($.inArray(ext, webTypes) > -1 || ext.includes('?'))) {
                files.push(Promise.resolve({ doc: doc, web: true }));
            }
        });

        downloadDocs(files);
    });
Pintor Zach
fuente
1

De lejos, la solución más fácil (al menos en ubuntu / linux):

  • hacer un archivo de texto con las URL de los archivos para descargar (es decir, file.txt)
  • coloque el 'file.txt' en el directorio donde desea descargar los archivos
  • abre la terminal en el directorio de descarga de la línea anterior
  • descargue los archivos con el comando 'wget -i file.txt'

Funciona de maravilla.

Martijn
fuente
No entiendo por qué esto está siendo rechazado. Esto funciona perfectamente, muchas gracias.
Martin Fürholz
1

Para resolver esto, creé una biblioteca JS para transmitir múltiples archivos directamente en un zip en el lado del cliente. La principal característica única es que no tiene límites de tamaño de memoria (todo se transmite) ni formato zip (usa zip64 si el contenido es de más de 4GB).

Dado que no realiza compresión, también es muy eficaz.

¡Busque "downzip" en npm o github !

DebboR
fuente
1

La siguiente secuencia de comandos hizo este trabajo con gracia.

var urls = [
'https://images.pexels.com/photos/432360/pexels-photo-432360.jpeg',
'https://images.pexels.com/photos/39899/rose-red-tea-rose-regatta-39899.jpeg'
];

function downloadAll(urls) {


  for (var i = 0; i < urls.length; i++) {
    forceDownload(urls[i], urls[i].substring(urls[i].lastIndexOf('/')+1,urls[i].length))
  }
}
function forceDownload(url, fileName){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.responseType = "blob";
    xhr.onload = function(){
        var urlCreator = window.URL || window.webkitURL;
        var imageUrl = urlCreator.createObjectURL(this.response);
        var tag = document.createElement('a');
        tag.href = imageUrl;
        tag.download = fileName;
        document.body.appendChild(tag);
        tag.click();
        document.body.removeChild(tag);
    }
    xhr.send();
}
Shyam Narayan
fuente
0

Estoy buscando una solución para hacer esto, pero descomprimir los archivos en javascript no fue tan limpio como me gustaba. Decidí encapsular los archivos en un solo archivo SVG.

Si tiene los archivos almacenados en el servidor (yo no), simplemente puede configurar el href en el SVG.

En mi caso, convertiré los archivos a base64 y los incrustaré en el SVG.

Editar: El SVG funcionó muy bien. Si solo va a descargar los archivos, ZIP podría ser mejor. Si va a mostrar los archivos, SVG parece superior.

VectorVortec
fuente
0

Al usar componentes Ajax, es posible iniciar múltiples descargas. Por lo tanto, debe usar https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow

Agregue una instancia de AJAXDownload a su página o lo que sea. Cree un AjaxButton y anule onSubmit. Cree un AbstractAjaxTimerBehavior y comience a descargar.

        button = new AjaxButton("button2") {

        private static final long serialVersionUID = 1L;

        @Override
        protected void onSubmit(AjaxRequestTarget target, Form<?> form)
        {
            MultiSitePage.this.info(this);
            target.add(form);

            form.add(new AbstractAjaxTimerBehavior(Duration.milliseconds(1)) {

                @Override
                protected void onTimer(AjaxRequestTarget target) {
                    download.initiate(target);
                }

            });     
        }

¡Feliz descarga!

kleenxcoder
fuente
javascrpt?!?!?!?!?!
bluejayke
0

Debajo del código 100% funcionando.

Paso 1 : pegue el código siguiente en el archivo index.html

<!DOCTYPE html>
<html ng-app="ang">

<head>
    <title>Angular Test</title>
    <meta charset="utf-8" />
</head>

<body>
    <div ng-controller="myController">
        <button ng-click="files()">Download All</button>
    </div>

    <script src="angular.min.js"></script>
    <script src="index.js"></script>
</body>

</html>

Paso 2 : pegue el código siguiente en el archivo index.js

"use strict";

var x = angular.module('ang', []);

    x.controller('myController', function ($scope, $http) {
        var arr = [
            {file:"http://localhost/angularProject/w3logo.jpg", fileName: "imageone"},
            {file:"http://localhost/angularProject/cv.doc", fileName: "imagetwo"},
            {file:"http://localhost/angularProject/91.png", fileName: "imagethree"}
        ];

        $scope.files = function() {
            angular.forEach(arr, function(val, key) {
                $http.get(val.file)
                .then(function onSuccess(response) {
                    console.log('res', response);
                    var link = document.createElement('a');
                    link.setAttribute('download', val.fileName);
                    link.setAttribute('href', val.file);
                    link.style.display = 'none';
                    document.body.appendChild(link);
                    link.click(); 
                    document.body.removeChild(link);
                })
                .catch(function onError(error) {
                    console.log('error', error);
                })
            })
        };
    });

NOTA : Asegúrese de que los tres archivos que se van a descargar se coloquen en la misma carpeta junto con los archivos angularProject / index.html o angularProject / index.js .

solanki ...
fuente
¿¿¿¿U rilly amasar ayng [el último maestro aire] ular para thuis / ???
bluejayke
0

Obtener una lista de URL con una llamada ajax y luego usar el complemento jquery para descargar varios archivos en paralelo.

  $.ajax({
        type: "POST",
        url: URL,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: data,
        async: true,
        cache: false,
        beforeSend: function () {
            blockUI("body");
        },
        complete: function () { unblockUI("body"); },
        success: function (data) {
           //here data --> contains list of urls with comma seperated
            var listUrls= data.DownloadFilePaths.split(',');
            listUrls.forEach(function (url) {
                $.fileDownload(url);
            });
            return false; 
        },
        error: function (result) {
            $('#mdlNoDataExist').modal('show');
        }

    });
Ali
fuente
0

Esta es la forma en que lo hago. Abro varios ZIP pero también otro tipo de datos (exporto el proyecto en PDF y al mismo tiempo muchos ZIP con documento).

Solo copio parte pasada de mi código. La llamada de un botón en una lista:

$url_pdf = "pdf.php?id=7";
$url_zip1 = "zip.php?id=8";
$url_zip2 = "zip.php?id=9";
$btn_pdf = "<a href=\"javascript:;\" onClick=\"return open_multiple('','".$url_pdf.",".$url_zip1.",".$url_zip2."');\">\n";
$btn_pdf .= "<img src=\"../../../images/icones/pdf.png\" alt=\"Ver\">\n";
$btn_pdf .= "</a>\n"

Entonces, una llamada básica a una rutina JS (¡reglas de vainilla!). aquí está la rutina JS:

 function open_multiple(base,url_publication)
 {
     // URL of pages to open are coma separated
     tab_url = url_publication.split(",");
     var nb = tab_url.length;
     // Loop against URL    
     for (var x = 0; x < nb; x++)
     {
        window.open(tab_url[x]);
      }

     // Base is the dest of the caller page as
     // sometimes I need it to refresh
     if (base != "")
      {
        window.location.href  = base;
      }
   }

El truco es NO dar el enlace directo del archivo ZIP sino enviarlo al navegador. Me gusta esto:

  $type_mime = "application/zip, application/x-compressed-zip";
 $the_mime = "Content-type: ".$type_mime;
 $tdoc_size = filesize ($the_zip_path);
 $the_length = "Content-Length: " . $tdoc_size;
 $tdoc_nom = "Pesquisa.zip";
 $the_content_disposition = "Content-Disposition: attachment; filename=\"".$tdoc_nom."\"";

  header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");   // Date in the past
  header($the_mime);
  header($the_length);
  header($the_content_disposition);

  // Clear the cache or some "sh..." will be added
  ob_clean();
  flush();
  readfile($the_zip_path);
  exit();
Pedro
fuente
-1
           <p class="style1">



<a onclick="downloadAll(window.links)">Balance Sheet Year 2014-2015</a>

</p>

<script>
 var links = [
  'pdfs/IMG.pdf',
  'pdfs/IMG_0001.pdf',
 'pdfs/IMG_0002.pdf',
 'pdfs/IMG_0003.pdf',
'pdfs/IMG_0004.pdf',
'pdfs/IMG_0005.pdf',
 'pdfs/IMG_0006.pdf'

];

function downloadAll(urls) {
  var link = document.createElement('a');

  link.setAttribute('download','Balance Sheet Year 2014-2015');
  link.style.display = 'none';

  document.body.appendChild(link);

  for (var i = 0; i < urls.length; i++) {
    link.setAttribute('href', urls[i]);
    link.click();
  }

  document.body.removeChild(link);
}
</script>

fuente