2012-02-08 5 views
48

Я хочу заставить браузер загрузить файл pdf.Как использовать Content-disposition для принудительного скачивания файла на жесткий диск?

Я использую следующий код:

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

Это делает браузер открыть PDF в новом окне, но я хочу, чтобы загрузить на жесткий диск, когда пользователь нажимает на нее.

Я нашел, что для этого используется Content-disposition, но как его использовать в моем случае?

+1

Как вы управляете заголовками? – Oded

+2

Возможный дубликат [Как реализовать Content-Disposition: attachment?] (Http://stackoverflow.com/questions/8875949/how-to-implement-content-disposition-attachment) – Quentin

ответ

83

На HTTP Response, где вы возвращаете файл PDF, обеспечивает заголовок распоряжения контента выглядит следующим образом:

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

См content-disposition на странице википедии MIME.

+6

i очень новое, чтобы Content-disposition – krish

+21

@ Криш - Мы все учимся где-то. – Oded

+0

@Oded: И если файл открывается локально * (или любые другие случаи без http-сервера) *? – user2284570

4

С недавних браузеров вы можете использовать HTML5 атрибут загрузки, а также:

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

Он поддерживается большинством браузеров, кроме последних MSIE11. Вы можете использовать polyfill, что-то вроде этого (обратите внимание, что это только для данных 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 /*@[email protected]*/false || !!document.documentMode; 
    } 

})(); 
+1

Похоже, что он имеет неплохую поддержку браузера, кроме IE 11 и мобильного сафари: http://caniuse.com/#feat=download –

+0

@StephenOstermiller Недавние браузеры поддерживают ES7 async/await и классы ES6 (кроме MSIE ofc.). Публичные сайты могут быть оптимизированы для MSIE, в то время как сайты-администраторы могут быть оптимизированы для других браузеров с новыми функциями. Или вы можете использовать polyfill MSIE. – inf3rno