Làm thế nào để sử dụng Định vị nội dung để buộc tải tệp xuống ổ cứng?


76

Tôi muốn buộc trình duyệt tải xuống một pdftệp.

Tôi đang sử dụng mã sau:

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

Nó làm cho trình duyệt mở pdf trong một cửa sổ mới, nhưng tôi muốn nó tải xuống ổ cứng khi người dùng nhấp vào.

Tôi thấy rằng nó Content-dispositionđược sử dụng cho việc này, nhưng làm thế nào để sử dụng nó trong trường hợp của tôi?


Câu trả lời:


124

Trên Phản hồi HTTP nơi bạn đang trả lại tệp PDF, hãy đảm bảo tiêu đề bố trí nội dung giống như sau:

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

Xem bố cục nội dung trên trang wikipedia MIME.


2
@Oded: Và trong trường hợp tệp được mở cục bộ (hoặc bất kỳ trường hợp nào khác mà không có máy chủ http) ?
user2284570

@ user2284570 - điều đó sẽ phụ thuộc vào cài đặt trình duyệt và hệ điều hành cụ thể.
Oded

1
@ user2284570 - không biết. Có vẻ đủ dễ dàng để kiểm tra cục bộ, không?
Oded

@Oded: bạn đã xem đến nhận xét cuối cùng của tôi về câu trả lời được liên kết chưa? Tệp không được tải xuống dưới dạng HTML. Ngoài ra còn có w3schools.com/tags/att_a_download.asp , nhưng tôi không biết nó tương đương với JavaScript.
user2284570

Rất hữu ích cho tôi, cảm ơn, tôi đã dành hàng giờ đồng hồ để tìm lý do tại sao Chrome không hiển thị tệp pdf trong trình xem của mình, vấn đề là tôi trả lại tệp ở dạng Respose như một tệp đính kèm. Vì vậy, trong trường hợp của tôi để tải xuống bản pdf trong Câu trả lời, tôi đã sử dụng Nội dung-Bố trí: tệp đính kèm; và để hiển thị một bản pdf, tôi đã sử dụng Nội dung-Bố trí: nội tuyến ;. Cảm ơn bạn rất nhiều cho câu trả lời của bạn.
Alexei Bondarev

14

Với các trình duyệt gần đây, bạn cũng có thể sử dụng thuộc tính tải xuống HTML5:

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

Nó được hỗ trợ bởi hầu hết các trình duyệt gần đây ngoại trừ MSIE11. Bạn có thể sử dụng polyfill, một cái gì đó như thế này (lưu ý rằng cái này chỉ dành cho dữ liệu, nhưng nó là một khởi đầu tốt):

(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
Dường như nó đã hỗ trợ trình duyệt khá tốt ngoại trừ IE 11 và safari di động: caniuse.com/#feat=download
Stephen Ostermiller

1
@StephenOstermiller Các trình duyệt gần đây cũng hỗ trợ các lớp ES7 async / await và ES6 (ngoại trừ MSIE ofc.) Các trang web công cộng có thể được tối ưu hóa cho MSIE trong khi các trang web quản trị có thể được tối ưu hóa cho các trình duyệt khác với các tính năng mới. Hoặc bạn có thể sử dụng polyfill MSIE.
inf3rno

1
Hiện được hỗ trợ rộng rãi nhưng lưu ý rằng hạn chế về nguồn gốc giống nhau áp dụng trong hầu hết (tất cả?) Trình duyệt.
rymo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.