среда, 29 октября 2014 г.

Вызов скачивания файла в браузере через JavaScript посредством создания iFrame

function iframeFileDownload (url, data) {
    var iframe = $('#download_file_iframe')
        , iframeDoc
        , iframeHTML ='<html><head></head><body><form method="GET" action="' + url + '">'
        , key;
    for (key in data) {
        if (data.hasOwnProperty(key)) {
            iframeHTML += '<input type="hidden" name="' + key + '" value="' + data[key] + '" />';
        }
    }
    iframeHTML += '</form></body></html>';
    if (iframe.length === 0) {
        iframe = $('<iframe id="download_file_iframe" style="display: none" src="about:blank"></iframe>');
        $('body').append(iframe);
    }
    iframeDoc = iframe[0].contentWindow || iframe[0].contentDocument;
    if (iframeDoc.document) {
        iframeDoc = iframeDoc.document;
    }
    iframeDoc.open();
    iframeDoc.write(iframeHTML);
    $(iframeDoc).find('form').submit();
}

// Как использовать
$('#someid').on('click', function() {
    iframeFileDownload('/download.action', {'param1': 1, 'param2': 2});
});

Скачивание файлов посредством AJAX-запроса не приводит к вызову окна с предложением сохранить файл.
Вы может использовать XMLHttpRequest для получения бинарного файла, но вы не сможете сохранить его на компьютер пользователя. Использование Flash снимает это ограничение, но не всегда удобно использовать Flash.
Поэтому в помощь нам прийдет iframe. iframe может существовать внутри DOM страницы, но в большинстве случаев он воспринимается браузером как отдельно окно. Динамически вставляя скрытый iframe в DOM и устанавливая его "src" на скачиваемый файл мы вызываем скачивание файла так, как-будто оно было вызвано в главном окне. Такой способ позволяет нам обойти проблему сбоя во время скачивания файла, приводящего к перезагрузке страницы.
Как любое обычное скачивание файла в основном окне, скачивание файла через iframe никогда не приведет к перезагрузке страницы, если скачивание было завершено успешно. Поэтому для определения успешного скачивания сервер должен установить в браузер cookie. Таким образом ответ сервера будет примерно таким:
Content-Disposition: attachment; filename=Report0.pdf
Set-Cookie: fileDownload=true; path=/
До тех пор пока мы не можем напрямую сказать был ли файл скачан успешно, мы должны проверять наличие cookie, которое должен был установить сервер.
Как только скачивание через iframe началось, то мы начинаем циклически проверять наличие cookie.
Если содержимое iframe во время скачивания файла изменится, то это будет означать, что при скачивании произошла ошибка.
А, если cookie было записано, то мы прекращаем проверку и удаляем iframe, потому что диалоговое окно с предолжением сохранить файл уже появилось на экране.

Комментариев нет:

Отправить комментарий