Html 单击按钮时,如何让用户下载多个文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18451856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I let a user download multiple files when a button is clicked?
提问by Grammin
So I have a httpd server running which has links to a bunch of files. Lets say the user selects three files from a file list to download and they're located at:
所以我有一个 httpd 服务器正在运行,它有一堆文件的链接。假设用户从文件列表中选择三个文件进行下载,它们位于:
mysite.com/file1
mysite.com/file2
mysite.com/file3
When they click the download button I want them to download these three files from the links above.
当他们单击下载按钮时,我希望他们从上面的链接下载这三个文件。
My download button looks something like:
我的下载按钮看起来像:
var downloadButton = new Ext.Button({
text: "Download",
handler: function(){
//download the three files here
}
});
采纳答案by Tanuj
The best way to do this is to have your files zipped and link to that:
最好的方法是将您的文件压缩并链接到该文件:
The other solution can be found here: How to make a link open multiple pages when clicked
可以在此处找到其他解决方案:单击链接时如何打开多个页面
Which states the following:
其中陈述如下:
HTML:
HTML:
<a href="#" class="yourlink">Download</a>
JS:
JS:
$('a.yourlink').click(function(e) {
e.preventDefault();
window.open('mysite.com/file1');
window.open('mysite.com/file2');
window.open('mysite.com/file3');
});
Having said this, I would still go with zipping the file, as this implementation requires JavaScript and can also sometimes be blocked as popups.
话虽如此,我仍然会压缩文件,因为这个实现需要 JavaScript,有时也可以作为弹出窗口被阻止。
回答by Dan
This was the method which worked best for me and didn't open up new tabs, but just downloaded the files/images I required:
这是最适合我的方法,并且没有打开新标签,而是下载了我需要的文件/图像:
var filesForDownload = [];
filesForDownload( { path: "/path/file1.txt", name: "file1.txt" } );
filesForDownload( { path: "/path/file2.jpg", name: "file2.jpg" } );
filesForDownload( { path: "/path/file3.png", name: "file3.png" } );
filesForDownload( { path: "/path/file4.txt", name: "file4.txt" } );
$jq('input.downloadAll').click( function( e )
{
e.preventDefault();
var temporaryDownloadLink = document.createElement("a");
temporaryDownloadLink.style.display = 'none';
document.body.appendChild( temporaryDownloadLink );
for( var n = 0; n < filesForDownload.length; n++ )
{
var download = filesForDownload[n];
temporaryDownloadLink.setAttribute( 'href', download.path );
temporaryDownloadLink.setAttribute( 'download', download.name );
temporaryDownloadLink.click();
}
document.body.removeChild( temporaryDownloadLink );
} );
回答by Lukasz Dynowski
I fond that executing click()
event on a
element inside a for loop
for multiple files download works only for limited number of files (10 files in my case). The only reason that would explain this behavior that made sense to me, was speed/intervals of downloads executed by click()
events.
我喜欢click()
在多个文件下载中的a
元素上执行事件for loop
仅适用于有限数量的文件(在我的情况下为 10 个文件)。可以解释这种对我有意义的行为的唯一原因是click()
事件执行的下载速度/间隔。
I figure out that, if I slow down execution of click()
event, then I will be able to downloads all files.
我发现,如果我减慢click()
事件的执行速度,那么我将能够下载所有文件。
This is solution that worked for me.
这是对我有用的解决方案。
var urls = [
'http://example.com/file1',
'http://example.com/file2',
'http://example.com/file3'
]
var interval = setInterval(download, 300, urls);
function download(urls) {
var url = urls.pop();
var a = document.createElement("a");
a.setAttribute('href', url);
a.setAttribute('download', '');
a.setAttribute('target', '_blank');
a.click();
if (urls.length == 0) {
clearInterval(interval);
}
}
I execute download event click()
every 300ms. When there is no more files to download urls.length == 0
then, I execute clearInterval
on interval
function to stop downloads.
我click()
每 300 毫秒执行一次下载事件。当没有更多的要下载的文件urls.length == 0
,然后,我执行clearInterval
的interval
功能停止下载。
回答by Matthew
You can either:
您可以:
- Zip the selected files and return the one zipped file.
- Open multiple pop-ups each prompting for a download.
- 压缩所选文件并返回一个压缩文件。
- 打开多个弹出窗口,每个提示下载。
Note - option one is objectively better.
注意 - 选项一客观上更好。
EditFound an option three: https://stackoverflow.com/a/9425731/1803682
编辑找到一个选项三:https: //stackoverflow.com/a/9425731/1803682
回答by suresh
<!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();
});
}
}]);
plunker example: https://plnkr.co/edit/XynXRS7c742JPfCA3IpE?p=preview
plunker 示例:https://plnkr.co/edit/XynXRS7c742JPfCA3IpE ?p =preview
回答by Iain M Norman
I've solved this a different way by using window.location. It works in Chrome, which fortunately is the only browser I had to support. Might be useful to someone. I'd initally used Dan's answer, which also needed the timeout I've used here or it only downloaded one file.
我通过使用 window.location 以不同的方式解决了这个问题。它适用于 Chrome,幸运的是它是我必须支持的唯一浏览器。可能对某人有用。我最初使用了丹的答案,这也需要我在这里使用的超时时间,或者它只下载了一个文件。
var linkArray = [];
linkArray.push("http://example.com/downloadablefile1");
linkArray.push("http://example.com/downloadablefile2");
linkArray.push("http://example.com/downloadablefile3");
function (linkArray) {
for (var i = 0; i < linkArray.length; i++) {
setTimeout(function (path) { window.location = path; }, 200 + i * 200, linkArray[i]);
}
};
回答by Zach Painter
This works in all browsers (IE11, Firefox, Microsoft Edge, Chrome and Chrome Mobile) My documents are in multiple select elements. The browsers seem to have issues when you try to do it too fast... So I used a timeout.
这适用于所有浏览器(IE11、Firefox、Microsoft Edge、Chrome 和 Chrome Mobile)我的文档位于多个选择元素中。当你尝试做得太快时,浏览器似乎有问题......所以我使用了超时。
<select class="document">
<option val="word.docx">some word document</option>
</select>
//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));
}
});
});
This solution uses promises:
此解决方案使用承诺:
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);
});
回答by M.S
Found the easiest way to do this. Works even with div!
找到了最简单的方法来做到这一点。即使使用 div 也能工作!
<div onclick="downloadFiles()">
<!--do not put any text in <a>, it should be invisible-->
<a href="path/file1" id="a1" download></a>
<a href="path/file2" id="a2" download></a>
<a href="path/file3" id="a3" download></a>
<script>
function downloadFiles() {
document.getElementById("a1").click();
document.getElementById("a2").click();
document.getElementById("a3").click();
}
</script>
Download
</div>
That's all, hope it helps.
就这些,希望有帮助。
回答by NoName
//It is possible when using Tampermonkey (Firefox or Chrome).
//They added the GM_Download command.
//You can use it like this download multiple files One time:
// ==UserScript==
// @name
// @description
// @match
// @grant
// @grant GM_download
function setup_reader(file) {
var name = file.name;
var reader = new FileReader();
reader.onload = function (e) {
var bin = e.target.result; //get file content
var lines = bin.split('\n');
for (var line = 0; line < lines.length; line++) {
console.log(lines[line]);
GM_download(lines[line], line + '.jpg');
}
}
// reader.readAsBinaryString(file);
reader.readAsText(file, 'utf-8');//
}
回答by PolyGlot
You can do it, creating mouse events and dispatching them to button. Sourse.
你可以做到,创建鼠标事件并将它们分派给按钮。源。
hrefList=['mysite.com/1.jpg', 'mysite.com/2.mp4', 'mysite.com/3.gif'];
buttonDownloadAll=document.createElement('a');
buttonDownloadAll.innerText='Download all';
buttonDownloadAll.href='';
buttonDownloadAll.download=false;
downloadFunc=function(){
buttonDownloadAll.setAttribute('onclick', '');
buttonDownloadAll.download=true;
for(var i=0; i<hrefList.length-1; i++){
buttonDownloadAll.href=hrefList[i];
var clickEvent = document.createEvent('MouseEvent');
clickEvent.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
buttonDownloadAll.dispatchEvent(clickEvent);
}
buttonDownloadAll.setAttribute('onclick', 'downloadFunc()');
buttonDownloadAll.download=false;
buttonDownloadAll.href='';
};
buttonDownloadAll.setAttribute('onclick', 'downloadFunc()');
document.body.appendChild(buttonDownloadAll);