Загрузка нескольких файлов без использования 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 файлов, потому что тогда они всегда должны разархивировать его сначала (что будет слишком сложно для некоторых, чтобы понять), и это замедляет их.
Ответы
Ответ 1
Таким образом, это возможно overkill, но работает в 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);
});
Ответ 2
jQuery плагин, который будет работать для вас:
github.com/biesiad/multiDownload
Ответ 3
Это может или не может решить вашу проблему, но здесь вы делаете общую ошибку. Ифрагмы не являются самозакрывающимися тегами. Многие браузеры не будут правильно разбирать этот 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>");
Ответ 4
Я знаю, что это старый вопрос, но недавно у меня была эта проблема, и я создал это решение, которое наилучшим образом отвечало моим потребностям (я не хотел использовать файлы 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.
Ответ 5
Вы можете позвонить для загрузки в цикле 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>