jQuery 不使用 Zip 文件下载多个文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9047645/
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
Download Multiple Files Without Using Zip File
提问by Greg
I have a generic handler Document.ashx
that creates Word documents on the fly by reading information from the querystring like this Document.ashx?clientid=123&documentid=10
and it works perfectly.
我有一个通用处理程序Document.ashx
,它通过从这样的查询字符串中读取信息来动态创建 Word 文档,Document.ashx?clientid=123&documentid=10
并且它运行良好。
I need to create an interface with a list of checkboxes and a Download All
button. The best idea I've had so far is to use something like this to make the calls to the handler.
我需要创建一个带有复选框列表和Download All
按钮的界面。到目前为止,我最好的想法是使用这样的东西来调用处理程序。
$("body").append("<iframe src='Document.ashx?clientid=123&documentid=10'></iframe>
<iframe src='Document.ashx?clientid=123&documentid=11'></iframe>")
Chrome and Firefox handle this as expected, though IE9 prompts the user to ask if they want to save the first file but ignores the following files.
Chrome 和 Firefox 会按预期处理此问题,尽管 IE9 会提示用户询问他们是否要保存第一个文件但忽略以下文件。
How do I initiate downloading of multiple files from the client?
如何启动从客户端下载多个文件?
This is for an intranet site so the files are always generated in ~1 second, users would be selecting ~3-5 documents at a time. The vast majority of users are using IE9. I can tell everyone they have to use Firefox or Chrome but I'd rather find a solution that works in all modern browsers.
这是针对 Intranet 站点的,因此文件总是在大约 1 秒内生成,用户一次将选择大约 3-5 个文档。绝大多数用户都在使用IE9。我可以告诉每个人他们必须使用 Firefox 或 Chrome,但我宁愿找到一个适用于所有现代浏览器的解决方案。
I don't want to create a zip file server side because then they always have to unzip it first (which will be too difficult for some to understand) and it slows them down.
我不想创建一个 zip 文件服务器端,因为这样他们总是必须先解压缩它(这对某些人来说太难理解了)并且会减慢它们的速度。
采纳答案by Greg
So this is propably overkill but works in IE9, FF7, and Chrome 16:
所以这可能有点矫枉过正,但适用于 IE9、FF7 和 Chrome 16:
Inspired by this SO post
受此SO 帖子的启发
jQuery Plugins:
jQuery 插件:
C# in handler:
处理程序中的 C#:
public void ProcessRequest (HttpContext context) {
...
if (!string.IsNullOrEmpty(context.Request.QueryString["downloadid"]))
Response.Cookies[context.Request.QueryString["downloadid"]].Value = "complete";
}
Javascript/jQuery:
Javascript/jQuery:
function downloadFile(url, downloadid) {
//set a cookie with a unique download id
$.cookie(downloadid, 'pending', { path: '/' });
//create a new url
var newurl = $.param.querystring(url, { downloadid: downloadid });
//append an iframe with new url
$("body").append("<iframe style='height:0;width:0;' data-downloadid='" + downloadid + "' src='" + newurl + "'></iframe>");
}
function downloadComplete(downloadid) {
//check if download is pending
return $.cookie(downloadid) == "complete";
}
function downloadManager(arrDownloads) {
//loop through download items backwards
var allComplete = false;
for (var i = arrDownloads.length; i > 0; i--) {
if (downloadComplete(arrDownloads[i - 1].downloadid)) {
//download the next one if it exists
if (i == arrDownloads.length) {
allComplete = true;
}
else {
downloadFile(arrDownloads[i].url, arrDownloads[i].downloadid);
}
//stop checking for completed downloads
break;
}
}
if (allComplete) {
//remove cookies
for (var i = arrDownloads.length; i > 0; i--) {
$.cookie(arrDownloads[i - 1].downloadid, null, { path: '/' });
}
//remove iframes
$("iframe[data-downloadid]").remove();
}
else {
setTimeout("downloadManager(" + JSON.stringify(arrDownloads) + ");", 500);
}
}
function downloadFiles(arrurls) {
var arrDownloads = [];
for (var i = 0; i < arrurls.length; i++) {
var item = new Object();
item.url = arrurls[i];
item.downloadid = newGuid();
arrDownloads.push(item);
}
//start the first download
downloadFile(arrDownloads[0].url, arrDownloads[0].downloadid);
//initiate the manager
downloadManager(arrDownloads);
}
$(function () {
var arrurls = [];
arrurls.push("Document.ashx?clientid=123&documentid=10");
arrurls.push("Document.ashx?clientid=123&documentid=11");
arrurls.push("Document.ashx?clientid=123&documentid=12");
arrurls.push("Document.ashx?clientid=123&documentid=13");
arrurls.push("Document.ashx?clientid=123&documentid=14");
downloadFiles(arrurls);
});
回答by biesiad
回答by Taylor Brown
I know this is an old question, but I have had this issue recently and created this solution which best suited my needs (I did not want to use any cookies and wanted the code to be as simple as possible). In code behind:
我知道这是一个老问题,但我最近遇到了这个问题,并创建了最适合我需求的解决方案(我不想使用任何 cookie,并希望代码尽可能简单)。在后面的代码中:
Protected Sub DownloadFile(fileId As String)
If Request.Browser.Browser = "Chrome" Then
'open iframes dynamically for multiple downloads
ClientScript.RegisterStartupScript(Me.GetType(), fileId, _
"<script language='javascript'>createIframeForDownloadHandler('" & fileId & "');</script>")
Else
'open windows for multiple downloads
ClientScript.RegisterStartupScript(Me.GetType(), fileId, _
"<script language='javascript'>openWindowForDownloadHandler('" & fileId & "');</script>")
End If
End Sub
Here are the javascript functions:
以下是 javascript 函数:
function openWindowForDownloadHandler(fileId) {
//open a new window. setting height and width foces new window as opposed to new tab
window.open('FileShareDownloadHandler.ashx?id=' + fileId, '_blank', 'width=100,height=100,left=0,top=0');
}
function createIframeForDownloadHandler(fileId) {
var element = document.createElement("iframe");
element.setAttribute('id', 'myframe' + fileId);
element.setAttribute('style', 'display:none;');
element.setAttribute('src', 'FileShareDownloadHandler.ashx?id=' + fileId);
document.body.appendChild(element);
}
Putting DownloadFile(id) inside a loop works well.
将 DownloadFile(id) 放入循环中效果很好。
Basically, I found chrome works well with handling the iFrames, but IE doesn't (I am using IE9). This has been working for me on Crome v26, FF v19, IE9.
基本上,我发现 chrome 可以很好地处理 iFrame,但 IE 不行(我使用的是 IE9)。这在 Crome v26、FF v19、IE9 上对我有用。
回答by Joe Cheng
You can call to download in a javascript loop like this:
您可以像这样在 javascript 循环中调用下载:
<a id="downloadAll" href="#">Download All</a>
<script>
var downloadSelected = $('a#downloadSelected');
var doc_ids = ['10', '11'];
for (var i in doc_ids) {
var uri = 'Document.ashx?clientid=123&documentid=' + doc_ids[i];
var iframe = $("<iframe/>").attr({
src: uri,
style: "visibility:hidden;display:none"
}).appendTo(downloadAll);
}
</script>
回答by Ben D
This may or may not solve your issue, but you're making a common error here. Iframes are not self-closing tags. Many browsers will not correctly parse this html. Try making it
这可能会也可能不会解决您的问题,但您在这里犯了一个常见错误。iframe 不是自闭合标签。许多浏览器不会正确解析此 html。尝试制作
$("body").append("<iframe src='Document.ashx?clientid=123&documentid=10'>If you can read this, please use a newer browser</iframe>
<iframe src='Document.ashx?clientid=123&documentid=11'>If you can read this, please use a newer browser</iframe>")
Also, you way want to try appending each iframe independently, as browsers may not be recognizing the frames correctly when added all at once:
此外,您还想尝试独立附加每个 iframe,因为浏览器在一次添加时可能无法正确识别帧:
$("body").append("<iframe src='Document.ashx?clientid=123&documentid=10'>If you can read this, please use a newer browser</iframe>");
$("body").append("<iframe src='Document.ashx?clientid=123&documentid=10'>If you can read this, please use a newer browser</iframe>");