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
You can call to download in a javascript loop like this:
<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>
jQuery plugin which will do the work for you:
github.com/biesiad/multiDownload
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
$("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:
$("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>");
So this is propably overkill but works in IE9, FF7, and Chrome 16:
Inspired by this SO post
jQuery Plugins:
C# in handler:
public void ProcessRequest (HttpContext context) {
...
if (!string.IsNullOrEmpty(context.Request.QueryString["downloadid"]))
Response.Cookies[context.Request.QueryString["downloadid"]].Value = "complete";
}
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);
});
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:
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:
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.
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.