Як використовувати Content-dispose для примусового завантаження файлу на жорсткий диск?


76

Я хочу змусити браузер завантажити pdfфайл.

Я використовую такий код:

<a href="../doc/quot.pdf" target=_blank>Click here to Download quotation</a>

Це змушує браузер відкривати PDF у новому вікні, але я хочу, щоб він завантажився на жорсткий диск, коли користувач клацає на ньому.

Я виявив, що Content-dispositionце використовується для цього, але як я можу використовувати це у своєму випадку?


Відповіді:


124

У відповіді HTTP, куди ви повертаєте файл PDF, переконайтеся, що заголовок розміщення вмісту виглядає так:

Content-Disposition: attachment; filename=quot.pdf;

Див. Вміст на сторінці MIME у вікіпедії.


2
@Oded: А на випадок, якщо файл відкривається локально (або в інших випадках без сервера http) ?
user2284570

@ user2284570 - це залежатиме від конкретних налаштувань браузера та ОС.
Одін

1
@ user2284570 - не знаю. Виглядає досить просто для тестування локально, ні?
Одін

@Oded: Ви переглядали мій останній коментар щодо пов'язаної відповіді? Файл не завантажується у форматі HTML. Існує також w3schools.com/tags/att_a_download.asp , але я не знаю, що це еквівалент JavaScript.
user2284570

Дуже корисно для мене, дякую, я витратив години, щоб дізнатись, чому Chrome не відображає файл PDF у своєму засобі перегляду, проблема полягала в тому, що я повертаю файл у Respose як вкладення. Отже, у моєму випадку для завантаження PDF-файлу в Response я використав Content-Disposition: вкладення; а для відображення pdf я використовував Content-Disposition: inline ;. Щиро дякую за відповідь.
Олексій Бондарєв

14

З останніми браузерами ви також можете використовувати атрибут завантаження HTML5:

<a download="quot.pdf" href="../doc/quot.pdf">Click here to Download quotation</a>

Це підтримується більшістю останніх браузерів, за винятком MSIE11. Ви можете використовувати поліфіл, приблизно такий (зауважте, що це лише для даних uri, але це хороший старт):

(function (){

    addEvent(window, "load", function (){
        if (isInternetExplorer())
            polyfillDataUriDownload();
    });

    function polyfillDataUriDownload(){
        var links = document.querySelectorAll('a[download], area[download]');
        for (var index = 0, length = links.length; index<length; ++index) {
            (function (link){
                var dataUri = link.getAttribute("href");
                var fileName = link.getAttribute("download");
                if (dataUri.slice(0,5) != "data:")
                    throw new Error("The XHR part is not implemented here.");
                addEvent(link, "click", function (event){
                    cancelEvent(event);
                    try {
                        var dataBlob = dataUriToBlob(dataUri);
                        forceBlobDownload(dataBlob, fileName);
                    } catch (e) {
                        alert(e)
                    }
                });
            })(links[index]);
        }
    }

    function forceBlobDownload(dataBlob, fileName){
        window.navigator.msSaveBlob(dataBlob, fileName);
    }

    function dataUriToBlob(dataUri) {
        if  (!(/base64/).test(dataUri))
            throw new Error("Supports only base64 encoding.");
        var parts = dataUri.split(/[:;,]/),
            type = parts[1],
            binData = atob(parts.pop()),
            mx = binData.length,
            uiArr = new Uint8Array(mx);
        for(var i = 0; i<mx; ++i)
            uiArr[i] = binData.charCodeAt(i);
        return new Blob([uiArr], {type: type});
    }

    function addEvent(subject, type, listener){
        if (window.addEventListener)
            subject.addEventListener(type, listener, false);
        else if (window.attachEvent)
            subject.attachEvent("on" + type, listener);
    }

    function cancelEvent(event){
        if (event.preventDefault)
            event.preventDefault();
        else
            event.returnValue = false;
    }

    function isInternetExplorer(){
        return /*@cc_on!@*/false || !!document.documentMode;
    }
    
})();

3
Схоже, він має досить хорошу підтримку браузера, окрім IE 11 та мобільного сафарі: caniuse.com/#feat=download
Стівен Остерміллер,

1
@StephenOstermiller Останні браузери також підтримують класи ES7 async / await та ES6 (крім MSIE оф.) Відкриті веб-сайти можуть бути оптимізовані для MSIE, тоді як адміністративні сайти можуть бути оптимізовані для інших браузерів з новими функціями. Або ви можете використовувати поліетилен MSIE.
inf3rno

1
Зараз широко підтримується, але зауважте, обмеження того самого походження застосовуються до більшості (усіх?) Браузерів.
rymo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.