不使用Zip文件下载多个文件

12

我有一个通用处理程序Document.ashx,通过读取查询字符串中的信息(如Document.ashx?clientid=123&documentid=10),即可即时创建Word文档,并且它能够完美地运作。

我需要创建一个界面,其中包含复选框列表和一个Download All按钮。到目前为止,我想到的最好的方法是使用类似下面的代码来调用处理程序。

$("body").append("<iframe src='Document.ashx?clientid=123&documentid=10'></iframe>
                  <iframe src='Document.ashx?clientid=123&documentid=11'></iframe>")

Chrome和Firefox可以正常处理下载多个文件,但IE9会提示用户是否要保存第一个文件,而忽略后面的文件。

我该如何在客户端初始化下载多个文件?

这是用于内部网站的,所以文件总是在约1秒钟内生成,用户一次选择大约3-5个文档。绝大多数用户使用IE9。我可以告诉每个人他们必须使用Firefox或Chrome,但我更希望找到适用于所有现代浏览器的解决方案。

我不想在服务器端创建zip文件,因为那样他们总是需要先解压缩(这对有些人来说会太困难),而且会减慢下载速度。


我要尝试类似于这个的东西 - Greg
5个回答

11

这可能有点过于复杂,但在IE9、FF7和Chrome 16中都有效:

灵感来源于这篇SO帖子

jQuery插件:

C#处理程序:

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);
});

这取决于第一次调用的成功。如果失败了,它将如何继续并调用下一个 downloadFile? - Muzammil Tamboli

5

在下载第一个文件后,Chrome仍会给您一个黄色的栏,上面写着“此网站正在尝试下载多个文件。您要允许吗?”http://dl.dropbox.com/u/3115379/screengrab_20120719101330.png - Greg
嗯...你正在尝试下载多个文件。黄色进度条是正确的。如果你想避免它,你可以在下载之间添加更多的延迟。查看“延迟”选项。 - biesiad
我在你的 GitHub 测试中使用了图片而不是 tar.zip,但在最新版本的 Chrome 中无法工作。 - shareef

0

这可能会解决你的问题,但你在这里犯了一个常见的错误。Iframes 不是自闭合标签。许多浏览器将无法正确解析此 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>")

此外,您可能想尝试独立添加每个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>");

3
使用两个$.append()语句效果更好(Chrome不会弹出有关下载多个文件的警告),但在IE9中仍然无法正常工作(它只能识别第一个文件)。 - Greg

0

我知道这是一个老问题,但最近我遇到了这个问题,并创建了这个最适合我的解决方案(我不想使用任何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

这里是 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);
}

将DownloadFile(id)放在循环内部可以很好地工作。

基本上,我发现Chrome很擅长处理iFrames,但IE不行(我正在使用IE9)。这在Crome v26,FF v19,IE9上对我有效。


0
您可以像这样在 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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接