只需一个操作即可下载多个文件

Ank*_*kur 103 web-applications http download

我不确定使用标准网络技术是否可行.

我希望用户能够在一个操作中下载多个文件.这是文件旁边的单击复选框,然后获取所有已检查的文件.

是否有可能 - 如果是的话,你建议采用什么基本策略.我知道我可以使用comets技术来创建触发HttpResponse的服务器端事件,但我希望有一种更简单的方法.

Mat*_*rný 76

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);
}
Run Code Online (Sandbox Code Playgroud)
<button onclick="downloadAll(window.links)">Test me!</button>
Run Code Online (Sandbox Code Playgroud)

  • 它在IE 11中不起作用,它只下载.jar(列表中的最后一项)它是完美的解决方案:( (5认同)
  • 不起作用,只下载了最后一个文件 (4认同)
  • 对于大多数现代浏览器来说,这不是正确的方法,只会下载最后一个文件。 (3认同)
  • 我正在处理许多文件类型,包括图片,这对我来说效果最好.但是,`link.setAttribute('download',null);`将我的所有文件重命名为null. (2认同)
  • 在Chrome v75,Windows 10中无法正常运行:唯一下载的文件是“ Minecraft.jar”。 (2认同)

Jac*_*kin 58

HTTP不支持一次下载多个文件.

有两种解决方案:

  • 打开x个窗口以启动文件下载(这将通过JavaScript完成)
  • 首选解决方案创建一个脚本来压缩文件

  • 为什么zip文件是**首选**解决方案?它为用户创建了一个额外的步骤(解压缩). (33认同)
  • 此页面包含创建ZIP文件的javascript.看看它有一个很好的例子的页面.https://stuk.github.io/jszip/ (4认同)
  • HTTP本身支持多部分消息格式。但是浏览器并不能从服务器端轻松地解析多部分响应,但是从技术上讲,这样做并不困难。 (3认同)
  • 这可以是一个很好的 JavaScript 解决方案 https://github.com/sindresorhus/multi-download (3认同)

Dmi*_*gin 53

您可以创建一组临时隐藏的iframe,通过GET或POST在其中启动下载,等待下载启动并删除iframe:

<!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>
Run Code Online (Sandbox Code Playgroud)

或者,没有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);
    });
  }
Run Code Online (Sandbox Code Playgroud)

  • 这在IE10中有效吗?我得到:对象不支持属性或方法'写' (2认同)

spe*_*ane 32

此解决方案适用于各种浏览器,不会触发警告.iframe这里我们不是创建一个,而是为每个文件创建一个链接.这可以防止弹出警告消息.

为了处理循环部分,我们使用setTimeout,这是它在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);
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 按钮不执行任何操作“Google Chrome 版本 76.0.3809.100(官方版本)(64 位)”。 (4认同)

Shy*_*yan 6

以下脚本优雅地完成了这项工作。

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();
}
Run Code Online (Sandbox Code Playgroud)


Thi*_*ilo 5

最简单的方法是将捆绑在一起的多个文件提供给ZIP文件.

我想你可以使用一堆iframe或弹出窗口启动多个文件下载,但从可用性的角度来看,ZIP文件仍然更好.谁想点击浏览器会显示的十个"另存为"对话框?

  • 我知道您的答案是从2010年开始的,但是现在很多用户都在使用智能手机浏览,其中有些默认情况下无法打开zip(一个伙伴告诉我他的Samsung S4 Active无法打开zip)。 (2认同)

Yir*_*her 5

iframe 的 jQuery 版本回答:

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);
            });
    });
}
Run Code Online (Sandbox Code Playgroud)