回答:
HTTPは、一度に複数のファイルのダウンロードをサポートしていません。
2つの解決策があります。
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>
link.setAttribute('download', null);
すべてのファイルの名前をnullに変更しました。
link.setAttribute('download',filename)
ループの内側を追加します。これにより、ファイルに任意の名前を付けることができます。また、URLを含まないファイル名である必要があります。最終的に2つの配列を送信することになりました。1つは完全なURL、もう1つはファイル名のみです。
Minecraft.jar
。ダウンロードされるファイルはのみです。
非表示の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>
または、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);
});
}
setTimeout()
?
このソリューションはブラウザー間で機能し、警告をトリガーしません。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);
}
<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>
Google Chrome Version 76.0.3809.100 (Official Build) (64-bit)
。
最も簡単な方法は、ZIPファイルにバンドルされた複数のファイルを提供することです。
一連のiframeまたはポップアップを使用して複数のファイルのダウンロードを開始できると思いますが、使いやすさの観点からは、ZIPファイルの方が優れています。ブラウザが表示する10個の[名前を付けて保存]ダイアログをクリックしたい人はいますか?
zipファイルの方が適切なソリューションであることに同意します...しかし、複数のファイルをプッシュする必要がある場合、私が思いついたソリューションは次のとおりです。IE 9以降(おそらく下位バージョンも-私はテストしていません)、Firefox、Safari、Chromeで動作します。Chromeは、サイトで初めて使用するときに複数のファイルをダウンロードするという同意を得るためのメッセージをユーザーに表示します。
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]);
}
この手法の唯一の副作用は、送信とダウンロードダイアログが表示されるまでに遅延が生じることです。この影響を最小限に抑えるには、こことこの質問で説明する手法を使用することをお勧めします。ブラウザがファイルのダウンロードを受信したときに、ダウンロードを開始することを確認するためにファイルにCookieを設定することからなる検出します。クライアント側でこのCookieを確認し、サーバー側で送信する必要があります。クッキーの適切なパスを設定することを忘れないでください。そうしないと、表示されない可能性があります。また、ソリューションを複数のファイルのダウンロードに適合させる必要があります。
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);
});
});
}
download(['http://nogin.info/cv.doc','http://nogin.info/cv.doc']);
ただし、これは画像ファイルのダウンロードには機能しません。
角度ソリューション:
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();
});
}
}]);
@Dmitry Noginの答えを改善するために:これは私の場合うまくいきました。
ただし、さまざまなOS /ブラウザの組み合わせでファイルダイアログがどのように機能するかは不明なので、テストは行われていません。(したがって、コミュニティwiki。)
<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>
これはすべてのブラウザー(IE11、firefox、Edge、Chrome、Chrome Mobile)で機能します。私のドキュメントは複数の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));
}
});
});
これはpromiseを使用するソリューションです。
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);
});
はるかに簡単な解決策(少なくともubuntu / linuxでは):
魅力のように機能します。
次のスクリプトはこの作業を正常に実行しました。
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();
}
これを行うための解決策を探していますが、JavaScriptでのファイルの解凍は、私が思ったほどきれいではありませんでした。ファイルを単一のSVGファイルにカプセル化することにしました。
サーバーにファイルを保存している場合(そうではありません)、SVGでhrefを設定するだけです。
私の場合、ファイルをbase64に変換し、SVGに埋め込みます。
編集:SVGは非常にうまく機能しました。ファイルをダウンロードするだけの場合は、ZIPの方が良いでしょう。ファイルを表示する場合は、SVGが優れているようです。
Ajaxコンポーネントを使用する場合、複数のダウンロードを開始することが可能です。したがって、https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blowを使用する必要があります
AJAXDownloadのインスタンスをページなどに追加します。AjaxButtonを作成し、onSubmitをオーバーライドします。AbstractAjaxTimerBehaviorを作成し、ダウンロードを開始します。
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);
}
});
}
ハッピーダウンロード!
以下のコードは100%機能しています。
ステップ1:下のコードを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>
ステップ2:下のコードを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);
})
})
};
});
注:ダウンロードする3つのファイルがすべて、angularProject / index.htmlまたはangularProject / index.jsファイルと同じフォルダーに配置されていることを確認してください。
ajax呼び出しでURLのリストを取得し、jqueryプラグイン を使用して複数のファイルを並列にダウンロードします。
$.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');
}
});
これが私のやり方です。複数のZIPを開きますが、他の種類のデータも開きます(私はPDFでプロジェクトをエクスポートし、同時にドキュメントとともに多くのZIPをエクスポートします)。
コードの過去の部分をコピーするだけです。リストのボタンからの呼び出し:
$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"
したがって、JSルーチンへの基本的な呼び出し(バニラルール!)。ここに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;
}
}
トリックは、ZIPファイルの直接リンクを提供するのではなく、ブラウザに送信することです。このような:
$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();
<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>