Загрузка PDF-файла с использованием JavaScript, совместимого с разными браузерами

Я могу загрузить PDF-файл с помощью AngularJS в Chrome, но, похоже, это не работает в последних версиях FireFox, Internet Explorer 11 или Edge (при условии, что это не работает и в IE10), и я знаю прокладка необходима для IE9. Не знаю, лучшая ли это прокладка для этого, если у кого-то есть мнение, но в настоящее время она, похоже, не работает. Я попробовал это с типом ответа blob и arraybuffer на всякий случай, если это имело значение, и это не так.

Все это противоречит тому, что caniuse указывает на использование URL-адресов BLOB-объектов. У кого-нибудь это работает в IE9 и выше, а также в последних двух версиях FF, и может указать, что я делаю неправильно?

$http({
    url: '/api/v1/download',
    method: 'GET',
    responseType: 'blob' // or 'arraybuffer'
}).then(function (response) {

    // Use the Blob object to create an object URL to download the file
    var url = URL.createObjectURL(response.data);
    // var url = URL.createObjectURL(new Blob([response], {type: 'application/pdf'})); // arraybuffer version

    // Create an anchor to perform download, but don't append to the DOM
    anchor.href = downloadUrl;
    anchor.download = filename;
    anchor.target = '_blank';
    anchor.click();

    URL.revokeObjectURL(downloadUrl);            
    anchor = null;

}).catch(function (reason) {

    console.log('FAIL', reason);
});

ОБНОВЛЕНИЕ

В настоящее время лучший (единственный) ответ работает для IE10, 11, Edge, FF и продолжает работать с Chrome. IE9 не будет работать с этим решением, если у кого-то есть другой polyfill/shim/other/etc, а Safari не поддерживает атрибут загрузки, поэтому решение в выбранном ответе не работает в SPA, поскольку оно просто перенаправляет текущую страницу. поэтому в обоих этих случаях я просто оставил заглушки TODO.

Это обновление опубликованного ответа с дополнительной информацией, добавленной в комментарии для всех, кто может использовать или, надеюсь, добавить, чтобы IE9 и Safari работали должным образом:

    function performDownload(blob, filename) {

        // IE9 has no API for handling downloads using Blob objects, and doesn't support the download attribute
        if(isIE() == 9) {

            // TODO: polyfill/shim/other... change response type to?
        }
        // Only works for IE10 and up, including Edge
        else if (typeof window.navigator.msSaveBlob !== 'undefined') {

            // Provides a prompt to save the file to a location of users choice
            window.navigator.msSaveBlob(blob, filename);
        }
        // Browsers that adhere to current standards can implement downloads
        // using the Blob object with the download anchor attribute
        // ---
        // NOTE: Edge 13+ is compliant with both these standards, but Edge 12
        // does not support the download anchor attribute so all versions
        // have been grouped to use the propriety `msSaveBlob` method
        else {

            // Use the Blob object to create an object URL to download the file
            var URL = window.URL;
            var downloadUrl = URL.createObjectURL(blob);

            var anchor = document.createElement('a');

            if(angular.isDefined(anchor.download)) {

                anchor.href = downloadUrl;
                anchor.download = filename;
                anchor.target = '_blank';
                document.body.appendChild(anchor); // Required by Firefox
                anchor.click();

                // Release the existing object URL, and the anchor
                $timeout(function () {
                    URL.revokeObjectURL(downloadUrl);
                    document.body.removeChild(anchor);
                    anchor = null;
                }, 100);
            }
            else {

                // TODO: Safari does not support the download anchor attribute...
            }
        }
    }

person mtpultz    schedule 05.01.2017    source источник
comment
Где элемент <a> добавляется к document.body? Отменяете ли вы Blob URL до загрузки ресурса?   -  person guest271314    schedule 06.01.2017
comment
Спасибо @guest271314 Я обнаружил, что приведенный ниже ответ соответствует тому, что мне нужно в отношении моего вопроса о совместимости браузера, поскольку я уже мог загрузить файл в Chrome, и все повторяющиеся вопросы указывают на тот же код, который у меня уже был, но работал только в Chrome. Мой вопрос был не в том, как скачать, а в том, как загрузить его в разных браузерах. Оказывается, Firefox требует, чтобы якорь находился в DOM, поэтому его нужно было добавлять, в отличие от Chrome; и IE10, 11 и Edge требуют msSaveBlob. Кроме того, application/octet-stream по другой ссылке имеет известные проблемы в Safari, согласно caniuse.   -  person mtpultz    schedule 06.01.2017
comment
javascript в дублирующемся вопросе не совпадает с javascript в текущем вопросе. javascript в связанном вопросе добавляет элемент <a> к document.body, как указано в первом комментарии. application/octet-stream подход - это не только ответ или подход, описанный во второй ссылке.   -  person guest271314    schedule 06.01.2017
comment
@guest271314 guest271314 Я имел в виду ответ JS, который вы дали на вопрос, и просто указал, почему я нашел ответ ниже более полезным, поскольку он охватывает все браузеры, кроме IE9. Хотя эти ответы не работают в IE10, 11 или Safari. Так что они не с точки зрения совместимости браузера.   -  person mtpultz    schedule 06.01.2017
comment
Не пробовал т.е. в какое-то время. В каких браузерах javascript по адресу stackoverflow.com/a/31763030 не возвращает ожидаемый результат?   -  person guest271314    schedule 06.01.2017
comment
Привет @guest271314, похоже, это не работает для IE9, 10 или 11. Только для Edge, Chrome и FF. IE10 и 11 иногда открывают пустую вкладку, а иногда предлагают открыть большой двоичный объект с помощью локального приложения, но оба не загружают файл. IE10 и 11 работают, если вы используете window.navigator.msSaveBlob. Единственная проблема заключается в том, что msSaveBlob нет в IE9, и я не могу найти никакого решения/полифилла/прокладки для IE9, который, к сожалению, все еще находится на нашем радаре разработки :(   -  person mtpultz    schedule 06.01.2017


Ответы (2)


Я успешно использовал это как в IE11, так и в Chrome:

function saveBlob(response, contentType, filename) {
    let blob = new Blob([response.arrayBuffer()], { type: contentType });
    if (typeof window.navigator.msSaveBlob !== 'undefined') {
        // IE workaround
        window.navigator.msSaveBlob(blob, filename);
    } else {
        let URL = window.URL;
        let downloadUrl = URL.createObjectURL(blob);
        if (filename) {
            let a = document.createElement('a');
            if (typeof a.download === 'undefined') {
                window.location.href = downloadUrl;
            } else {
                a.href = downloadUrl;
                a.download = filename;
                document.body.appendChild(a);
                a.click();
            }
        } else {
            window.location.href = downloadUrl;
        }
        // cleanup
        setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); 
    }
}
person dmungin    schedule 05.01.2017
comment
Спасибо, это прекрасно работает. Это решение работает в IE10, 11, Edge, FF и Chrome. Нужно протестировать его в Safari, а в IE9 нужна прокладка для Blob, а также msSaveBlob. Даже не знаю, как протестировать IE9, даже если бы я нашел полифилл для msSaveBlob. - person mtpultz; 06.01.2017
comment
Если вы хотите протестировать старые версии IE, Microsoft создала несколько инструментов для этого developer.microsoft.com/en-us/microsoft-edge/tools/vms - person Andrew Diamond; 06.01.2017
comment
Большое спасибо, @AndrewDiamond. В итоге я купил browserstack.com на несколько месяцев, так как это позволило мне протестировать IE9+, Chrome , и Firefox пару лет назад на Windows 7, 8, 8.1, 10 и Safari 8+ на iOS для Yosemite+, а также множество мобильных версий каждого на разных устройствах. - person mtpultz; 09.01.2017
comment
Этот парень спас мне жизнь. - person jrlmx2; 29.08.2017

Попробуй это. он проверяет браузер и соответственно сохраняет файл

saveFile(response: any, fileName: string) {
    let browser = navigator.userAgent.toLowerCase();
        if(browser.indexOf('trident') == -1){
            let dataType = response.type;
            let binaryData = [];
            binaryData.push(response);
            let downloadLink = document.createElement('a');
            downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: dataType }));
            downloadLink.setAttribute('download', fileName);
            document.body.appendChild(downloadLink);
            downloadLink.click();
        }
        else{
            window.navigator.msSaveBlob(response, fileName);
        }
}
person Ajmal faiz    schedule 14.12.2020