Скачать несколько файлов без использования Zip-файла

У меня есть общий обработчик Document.ashx, который создает документы Word на лету, считывая информацию из строки запроса, подобной этой Document.ashx?clientid=123&documentid=10, и он отлично работает.

Мне нужно создать интерфейс со списком флажков и кнопкой 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-файл на стороне сервера, потому что тогда им всегда придется сначала распаковывать его (что для некоторых будет слишком сложно понять), и это замедляет их работу.


person Greg    schedule 28.01.2012    source источник
comment
Я попробую что-то вроде это   -  person Greg    schedule 29.01.2012


Ответы (5)


Так что это, возможно, излишне, но работает в IE9, FF7 и Chrome 16:

Вдохновленный этой записью SO

Плагины JQuery:

С# в обработчике:

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);
});
person Greg    schedule 29.01.2012
comment
Это зависит от успеха первого звонка. Что, если это не удастся, как он продолжит работу и вызовет downloadFile для следующего? - person Muzammil Tamboli; 09.02.2017

Плагин jQuery, который сделает всю работу за вас:

github.com/biesiad/multiDownload

person biesiad    schedule 19.07.2012
comment
Chrome по-прежнему показывает желтую полосу с надписью «Этот сайт пытается загрузить несколько файлов». Вы хотите разрешить это? после загрузки первого файла. dl.dropbox.com/u/3115379/screengrab_20120719101330.png - person Greg; 19.07.2012
comment
Ну... вы пытаетесь загрузить несколько файлов. Желтая полоса правильная. Если вы хотите избежать этого, вы можете добавить больше задержки между загрузками. Проверьте опцию «задержка». - person biesiad; 25.07.2012
comment
я поместил изображения вместо tar.zip в ваш тест github и не работал с последней версией chrome - person shareef; 06.05.2016

Это может или не может решить вашу проблему, но здесь вы совершаете распространенную ошибку. фреймы не являются самозакрывающимися тегами. Многие браузеры не будут правильно анализировать этот 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>");
person Ben D    schedule 28.01.2012
comment
Использование 2 операторов $.append() работало лучше (Chrome не выдавал предупреждение о загрузке нескольких файлов), но по-прежнему не работает в IE9 (он распознает только первый файл) - person Greg; 29.01.2012

Я знаю, что это старый вопрос, но недавно у меня возникла эта проблема, и я создал это решение, которое лучше всего соответствовало моим потребностям (я не хотел использовать файлы 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) внутри цикла работает хорошо.

В принципе, я обнаружил, что хром хорошо работает с обработкой iFrames, а IE - нет (я использую IE9). У меня это работает на Crome v26, FF v19, IE9.

person Taylor Brown    schedule 25.04.2013

Вы можете вызвать загрузку в цикле 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>
person Joe Cheng    schedule 12.12.2016