Buộc phải mở Lưu Lưu Như bật lên bật lên tại liên kết văn bản, nhấp vào PDF trong HTML


173

Tôi có một số danh mục PDF kích thước lớn tại trang web của mình và tôi cần liên kết chúng với mục tải xuống. Khi tôi googled, tôi tìm thấy một điều như vậy được ghi chú dưới đây. Nó sẽ mở cửa sổ bật lên " Lưu dưới dạng ... " tại liên kết nhấp vào ...

 <head>
    <meta name="content-disposition" content="inline; filename=filename.pdf">
    ...

Nhưng nó không hoạt động: / Khi tôi liên kết đến một tệp như bên dưới, nó chỉ liên kết đến tệp và đang cố mở tệp.

    <a href="filename.pdf" title="Filie Name">File name</a>

CẬP NHẬT (theo câu trả lời dưới đây):

Như tôi thấy không có giải pháp đa trình duyệt đáng tin cậy 100% cho việc này. Có lẽ cách tốt nhất là sử dụng một trong các dịch vụ web được liệt kê bên dưới và đưa ra liên kết tải xuống ...


1
không phục vụ mimetype cho các tập tin pdf.
bhups

Tôi đã thử giải pháp cập nhật của bạn, artmania - nhưng vấn đề tương tự tôi gặp phải trong Safari đã xảy ra. Tôi nhận được những gì trông giống như PDF trong cửa sổ trình duyệt và chỉ khi tôi nhấp vào tab "xem trước" hoặc "tải xuống" ở phía dưới, tôi mới nhận được tính năng tìm kiếm mà tôi rất cần.
thạch cao


tương tự nhưng ít loại tệp cụ thể hơn: stackoverflow.com/questions/1465573/ Từ
Ciro Santilli 冠状 病 六四 事件

Câu trả lời:


267

Từ câu trả lời để Buộc trình duyệt lưu tệp như sau khi nhấp vào liên kết :

<a href="path/to/file" download>Click here to download</a>

17
Tại thời điểm nhận xét này, downloadthuộc tính được giới hạn ở Chrome, Firefox và Opera. Ngay cả các phiên bản gần đây của IE và Safari cũng không hỗ trợ nó. Để được hỗ trợ trong tương lai: kiểm tra caniuse.com/#feat=d Download !
Sygmoral

Kiểm tra lỗi Netbeans phàn nàn về nó, nhưng nó có vẻ hoạt động tốt. Bạn có thể chỉ định tên sơ bộ cho tệp mới như vậy: download = "myFile.txt"
Yster

1
Điều này hoạt động trong Edge tại thời điểm viết bình luận này và dường như là cách duy nhất có thể để ngăn chặn các tệp PDF siêu liên kết mở trong nỗ lực rất kém của Edge đối với trình xem PDF.

Tại thời điểm nhận xét này, tôi đã thử nghiệm nó trên Chrome, Opera, Edge, Mozilla. Tất cả mới nhất. Đang làm việc trên tất cả ngoại trừ trên Mozilla.
SI

7
Điều này chỉ hoạt động cho các liên kết cùng nguồn gốc, như được đề cập trên caniuse.com/#feat=d Download . Nếu các liên kết của bạn có nguồn gốc chéo, tùy chọn duy nhất của bạn (hiện tại) là buộc loại phản hồi thành "application / octet-stream", như nhiều câu trả lời gợi ý. Nếu bạn không có quyền truy cập vào máy chủ, thì bạn có thể thử ủy quyền và đặt tiêu đề phản hồi theo cách thủ công.
jean-baptiste

80
<a href="file link" download target="_blank">Click here to download</a>

Nó hoạt động với tôi trong Firefox và Chrome.


2
Mặc dù vậy, nó giống hệt như câu trả lời hàng đầu hiện tại, từ Ayush Gupta năm 2013. Tuy nhiên, điều target="_blank"này có thể giúp sử dụng một chút cho các trình duyệt không hỗ trợ, mặc dù (PDF sau đó mở trong một cửa sổ / tab mới, thay vì ghi đè lên trang hiện tại).
Sygmoral

3
Đối với tôi, target="_blank"là cần thiết vì downloadchỉ thất bại trong việc kích hoạt tải xuống đúng cách (Chrome)
casraf

2
Nếu bạn đưa ra một chuỗi trong downloadthuộc tính, nó sẽ được sử dụng làm tên tệp. Tôi đang sử dụng nó trong mô tả người dùng mọi lúc.
franespase

34

Thẻ meta không phải là một cách đáng tin cậy để đạt được kết quả này. Nói chung, bạn thậm chí không nên làm điều này - nó nên để lại cho người dùng / tác nhân người dùng để quyết định làm gì với nội dung bạn cung cấp. Người dùng luôn có thể buộc trình duyệt của họ tải xuống tệp nếu họ muốn.

Nếu bạn vẫn muốn buộc trình duyệt tải xuống tệp, hãy sửa đổi trực tiếp các tiêu đề HTTP. Đây là một ví dụ mã PHP:

$path = "path/to/file.pdf";
$filename = "file.pdf";
header('Content-Transfer-Encoding: binary');  // For Gecko browsers mainly
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT');
header('Accept-Ranges: bytes');  // Allow support for download resume
header('Content-Length: ' . filesize($path));  // File size
header('Content-Encoding: none');
header('Content-Type: application/pdf');  // Change the mime type if the file is not PDF
header('Content-Disposition: attachment; filename=' . $filename);  // Make the browser display the Save As dialog
readfile($path);  // This is necessary in order to get it to actually download the file, otherwise it will be 0Kb

Lưu ý rằng đây chỉ là một phần mở rộng cho giao thức HTTP; một số trình duyệt có thể bỏ qua nó.


4
Trong thực tế tôi tin rằng điều này được thực hiện rộng rãi.
Matthew Wilson

Đây là giải pháp tốt nhất, rắc rối miễn phí và hoạt động. Bạn có thể tải trực tiếp bất kỳ loại tệp nào bằng phương pháp này. +1
casraf

3
Mã hóa chuyển nội dung không tồn tại trong HTTP. Mã hóa nội dung: không có gì là vô dụng.
Julian Reschke

GHI CHÚ trong câu trả lời của bạn, rằng tệp IF là từ máy chủ / tên miền bên ngoài, thì câu trả lời này có thể không phải là giải pháp ...
T.Todua

Tôi muốn thêm rằng tôi đã bị lỗi mã này hoặc mã tương tự trên một số máy chủ nhất định khi các tệp trở nên lớn (> 80 MB trong trường hợp của tôi). Sử dụng ob_end_flush()cũng không giúp được gì.
Hendrik

22

Tôi đã có vấn đề tương tự và tìm thấy một giải pháp đã làm việc rất tốt cho đến nay. Bạn đặt đoạn mã sau vào .htaccesstệp của mình :

<FilesMatch "\.(?i:pdf)$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>

Nó đến từ Buộc một tệp để tải xuống thay vì hiển thị trong trình duyệt .


4
Điều này hoạt động tốt, vì tôi có một thư mục tài liệu cụ thể để tải xuống. Tôi đã bỏ qua ForceType, chỉ để cho các loại giữ nguyên trạng. Tôi cũng không cần trường hợp không nhạy cảm; Của tôi dường như không phân biệt chữ hoa chữ thường. Tôi đã thêm một vài loại bổ sung, bao gồm tùy chọn-x cho các tiện ích mở rộng Office cũ / mới:<FilesMatch "\.(pdf|xlsx?|docx?)$">
goodeye

Điều này đã làm việc tuyệt vời, ngay cả trong OSX Safari, nơi mà các câu trả lời khác (bao gồm cả câu trả lời được chấp nhận, như một người bình luận đã chỉ ra ở đó) bị giới hạn ở một số trình duyệt hỗ trợ tính năng HTML đã cho. Điều này có vẻ lý tưởng hơn đối với tôi vì nó hoạt động trên bảng, mặc dù nó yêu cầu quyền truy cập cấp cao hơn vào các tệp cấu hình máy chủ.
bwright

Bạn cũng có thể đặt quyền đó vào tệp apache.conf của mình, tôi không sử dụng .htaccess vì nó cần nhiều tài nguyên hơn.
Michael Fever

Làm thế nào một trang web lưu trữ Windows sẽ thực hiện điều này, vì họ không thể đọc các tập tin htaccess?
PoloHoleSet

9

Tôi đã tìm thấy một giải pháp rất đơn giản cho Firefox (chỉ hoạt động với người thân chứ không phải trực tiếp): add type="application/octet-stream":

<a href="./file.pdf" id='example' type="application/octet-stream">Example</a>

1
@Martin Chrome trên Chrome OS và Firefox trên Linux. Hóa ra các tập tin cần phải là cục bộ để nó hoạt động. My href là một url để lưu trữ đám mây.
ttfreeman

7

Hãy thử thêm dòng này vào tệp .htaccess của bạn.

AddType application/octet-stream .pdf

Tôi hy vọng nó sẽ hoạt động vì nó độc lập với trình duyệt.


Tôi muốn biết lý do tại sao điều này đã bị hạ thấp - đó là một trong những phương pháp và công việc đơn giản nhất: css-tricks.com/snippets/htaccess/ trộm
Nathan Hornby

Mọi người cố gắng sửa đổi chức năng cốt lõi của một máy chủ trên các trang web lưu trữ miễn phí và sau đó tải xuống vì họ không thể làm cho nó hoạt động. Mọi giải pháp khác sẽ có sự cẩn thận vì đó là một "hack" để thay thế điều này.
Giỏ hàng bị bỏ rơi

Tôi đang hạ thấp nó bởi vì đó là giải pháp sai cho vấn đề. Đó là một ý tưởng tồi để gây rối với các loại tài nguyên.
Brad

@NathanHornby - Tôi đã không đánh giá thấp nó, nhưng điều này sẽ không hoạt động đối với bất kỳ trang web lưu trữ Windows nào, vì họ không sử dụng .htaccess.
PoloHoleSet

Tôi đã không downvote, nhưng giải pháp này ảnh hưởng mù quáng TẤT CẢ các tệp của hậu tố đó. Nó bừa bãi và do đó sẽ không thích hợp trong mọi trường hợp.
JBH

6

Nói chung, điều đó xảy ra, bởi vì một số cài đặt trình duyệt hoặc trình cắm trực tiếp mở PDF trong cùng một cửa sổ như một trang web đơn giản.

Sau đây có thể giúp bạn. Tôi đã thực hiện nó trong PHP một vài năm trước. Nhưng hiện tại tôi không làm việc trên nền tảng đó.

<?php
    if (isset($_GET['file'])) {
        $file = $_GET['file'];
        if (file_exists($file) && is_readable($file) && preg_match('/\.pdf$/',$file)) {
            header('Content-type: application/pdf');
            header("Content-Disposition: attachment; filename=\"$file\"");
            readfile($file);
        }
    }
    else {
        header("HTTP/1.0 404 Not Found");
        echo "<h1>Error 404: File Not Found: <br /><em>$file</em></h1>";
    }
?>

Lưu ở trên dưới dạng download.php .

Lưu đoạn mã nhỏ này dưới dạng tệp PHP ở đâu đó trên máy chủ của bạn và bạn có thể sử dụng nó để tải xuống tệp trong trình duyệt, thay vì hiển thị trực tiếp. Nếu bạn muốn phân phát các tệp khác ngoài PDF, hãy xóa hoặc chỉnh sửa dòng 5.

Bạn có thể sử dụng nó như vậy:

Thêm liên kết sau vào tệp HTML của bạn.

<a href="download.php?file=my_pdf_file.pdf">Download the cool PDF.</a>

Tham khảo từ: Blog này


7
Đây dường như là một cách hay để phục vụ mọi tệp trên máy chủ của bạn cho bất kỳ ai chú ý. download.php?file=database_password_file.phpví dụ.
pbarney

5

Chỉ cần đặt mã dưới đây vào .htaccesstập tin của bạn :

AddType application/octet-stream .csv
AddType application/octet-stream .xls
AddType application/octet-stream .doc
AddType application/octet-stream .avi
AddType application/octet-stream .mpg
AddType application/octet-stream .mov
AddType application/octet-stream .pdf

Hoặc bạn cũng có thể thực hiện thủ thuật bằng JavaScript

element.setAttribute( 'download', whatever_string_you_want);

1
Điều này có phải giả định máy chủ web là Apache không?
Peter Mortensen


4

Một cách thực sự đơn giản để đạt được điều này, mà không cần sử dụng các trang web tải xuống bên ngoài hoặc sửa đổi các tiêu đề, v.v. là chỉ cần tạo một tệp ZIP với tệp PDF bên trong và liên kết trực tiếp đến tệp ZIP. Điều này sẽ LUÔN kích hoạt hộp thoại Lưu / Mở và mọi người vẫn dễ dàng nhấp đúp vào cửa sổ PDF mà chương trình được liên kết với .zip được khởi chạy.

Câu hỏi tuyệt vời của BTW, tôi cũng đang tìm câu trả lời, vì hầu hết các plugin PDF nhúng trình duyệt mất rất nhiều thời gian để hiển thị mọi thứ (và sẽ thường treo trình duyệt trong khi PDF đang tải).


31
Khả năng sử dụng khủng khiếp. Nhiều người dùng cuối sẽ không biết phải làm gì với tệp zip.
CodeWar Warrior

1
Đôi khi solutioans đơn giản là giải pháp tốt nhất!
elrado

1
Không phải là một giải pháp tốt. Tôi có chính xác vấn đề đó với Firefox và một tệp ZIP. Tôi nên làm gì? ZIP tập tin? Trong trường hợp đó, sửa đổi các tiêu đề HTTP có thể là một giải pháp nhưng tôi không có quyền truy cập vào đó.
Arnaud Weil

2

Một giải pháp phía máy chủ tương thích hơn, cho đến khi thuộc tính "tải xuống" được triển khai trong tất cả các trình duyệt.

Một ví dụ Python có thể là một trình xử lý yêu cầu HTTP tùy chỉnh cho một filestore. Các liên kết trỏ đến filestore được tạo như thế này:

http://www.myfilestore.com/filestore/13/130787e71/doad_as/desiredName.pdf

Đây là mã:

class HTTPFilestoreHandler(SimpleHTTPRequestHandler):

    def __init__(self, fs_path, *args):
        self.fs_path = fs_path                          # Filestore path
        SimpleHTTPRequestHandler.__init__(self, *args)

    def send_head(self):
        # Overwrite SimpleHTTPRequestHandler.send_head to force download name
        path = self.path
        get_index = (path == '/')
        self.log_message("path: %s" % path)
        if '/download_as/' in path:
            p_parts = path.split('/download_as/')
            assert len(p_parts) == 2, 'Bad download link:' + path
            path, download_as = p_parts
        path = self.translate_path(path )
        f = None
        if os.path.isdir(path):
            if not self.path.endswith('/'):
                # Redirect browser - doing basically what Apache does
                self.send_response(301)
                self.send_header("Location", self.path + "/")
                self.end_headers()
                return None
            else:
                return self.list_directory(path)
        ctype = self.guess_type(path)
        try:
            f = open(path, 'rb')
        except IOError:
            self.send_error(404, "File not found")
            return None
        self.send_response(200)
        self.send_header("Content-type", ctype)
        fs = os.fstat(f.fileno())
        self.send_header("Expires", '0')
        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
        self.send_header("Cache-Control", 'must-revalidate, post-check=0, pre-check=0')
        self.send_header("Content-Transfer-Encoding", 'binary')
        if download_as:
            self.send_header("Content-Disposition", 'attachment; filename="%s"' % download_as)
        self.send_header("Content-Length", str(fs[6]))
        self.send_header("Connection", 'close')
        self.end_headers()
        return f


class HTTPFilestoreServer:

    def __init__(self, fs_path, server_address):
        def handler(*args):
            newHandler = HTTPFilestoreHandler(fs_path, *args)
            newHandler.protocol_version = "HTTP/1.0"
        self.server = BaseHTTPServer.HTTPServer(server_address, handler)

    def serve_forever(self, *args):
        self.server.serve_forever(*args)


def start_server(fs_path, ip_address, port):
    server_address = (ip_address, port)
    httpd = HTTPFilestoreServer(fs_path, server_address)

    sa = httpd.server.socket.getsockname()
    print "Serving HTTP on", sa[0], "port", sa[1], "..."
    httpd.serve_forever()

2

Một cách rất dễ dàng để làm điều này, nếu bạn cần buộc tải xuống cho một liên kết duy nhất trên trang của mình, là sử dụng thuộc tính tải xuống HTML5 trong liên kết href.

Xem: http://davidwalsh.name/doad-attribution

với điều này, bạn có thể đổi tên tập tin mà người dùng sẽ tải xuống và đồng thời nó buộc tải xuống.

Đã có một cuộc tranh luận liệu đây có phải là một thực tiễn tốt hay không, nhưng trong trường hợp của tôi, tôi có một trình xem được nhúng cho một tệp PDF và trình xem không cung cấp một liên kết tải xuống, vì vậy tôi phải cung cấp một liên kết riêng. Ở đây tôi muốn đảm bảo rằng người dùng không mở tệp PDF trong trình duyệt web, điều này sẽ gây nhầm lẫn.

Điều này sẽ không cần thiết mở hộp thoại lưu dưới dạng, nhưng sẽ tải liên kết thẳng đến đích tải xuống được đặt trước. Và tất nhiên nếu bạn đang làm một trang web cho người khác và cần họ viết các thuộc tính thủ công cho các liên kết của họ có lẽ là một ý tưởng tồi, nhưng nếu có cách để đưa thuộc tính vào các liên kết, đây có thể là một giải pháp nhẹ.


1

Đây là bài viết cũ nhưng đây là giải pháp của tôi trong JavaScript khi sử dụng thư viện jQuery.

<script>
(function($){
    var download = [];
    $('a.force-download, .force-download a').each(function(){
        // Collect info
        var $this = $(this),
            $href = $this.attr('href'),
            $split = $href.split('/'),
            $name = document.title.replace(/[\W_]/gi, '-').replace(/-{2,}/g, '-'); // get title and clean it for the URL

        // Get filename from URL
        if($split[($split.length-1)])
        {
            $tmp = $split[($split.length-1)];
            $tmp = $tmp.split('.');
            $name = $tmp[0].replace(/[\W_]/gi, '-').replace(/-{2,}/g, '-');
        }

        // If name already exists, put timestamp there
        if($.inArray($name, download) > -1)
        {
            $name = $name + '-' + Date.now().replace(/[\W]/gi, '-');
        }

        $(this).attr("download", $name);
        download.push($name);
    });
}(jQuery || window.jQuery))
</script>

Bạn chỉ cần sử dụng lớp force-downloadbên trong <a>thẻ của mình và sẽ buộc tải xuống tự động. Bạn cũng có thể thêm nó vào cha mẹ divvà sẽ chọn tất cả các liên kết bên trong nó.

Thí dụ:

<a href="/some/good/url/Post-Injection_Post-Surgery_Instructions.pdf" class="force-download" target="_blank">Download PDF</a>

Điều này rất tốt cho WordPress và bất kỳ hệ thống hoặc trang web tùy chỉnh nào khác.


0

Sau tên tệp trong mã HTML tôi thêm ?forcedownload=1

Đây là cách đơn giản nhất để tôi kích hoạt hộp thoại để lưu hoặc tải xuống.


0

Nếu bạn có một plugin trong trình duyệt biết cách mở tệp PDF, nó sẽ mở trực tiếp. Giống như trong trường hợp hình ảnh và nội dung HTML.

Vì vậy, cách tiếp cận khác là không gửi loại MIME của bạn trong phản hồi. Bằng cách này, trình duyệt sẽ không bao giờ biết nên mở plugin nào. Do đó nó sẽ cung cấp cho bạn một hộp thoại Lưu / Mở .


Điều đó khó đạt được vì đó là máy chủ gửi loại mime và khi liên kết trực tiếp đến tệp PDF, bạn không thể thay đổi tiêu đề.
Karel Petranek

0

Tôi chỉ gặp một vấn đề rất giống với vấn đề được thêm vào mà tôi cần để tạo liên kết tải xuống các tệp bên trong tệp ZIP.

Trước tiên tôi đã cố gắng tạo một tệp tạm thời, sau đó cung cấp một liên kết đến tệp tạm thời, nhưng tôi thấy rằng một số trình duyệt sẽ chỉ hiển thị nội dung (tệp CSV Excel) thay vì cung cấp để tải xuống. Cuối cùng, tôi tìm thấy giải pháp bằng cách sử dụng một servlet. Nó hoạt động cả trên Tomcat và GlassFish và tôi đã thử nó trên Internet Explorer 10 và Chrome.

Servlet lấy tên đường dẫn đầy đủ đến tệp ZIP và tên của tệp bên trong mã zip cần được tải xuống.

Trong tệp tin JSP của tôi, tôi có một bảng hiển thị tất cả các tệp bên trong zip, với các liên kết có nội dung: onclick='download?zip=<%=zip%>&csv=<%=csv%>'

Mã servlet nằm trong download.java:

package myServlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.zip.*;
import java.util.*;

// Extend HttpServlet class
public class download extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        PrintWriter out = response.getWriter(); // now we can write to the client

        String filename = request.getParameter("csv");
        String zipfile = request.getParameter("zip");

        String aLine = "";

        response.setContentType("application/x-download");
        response.setHeader( "Content-Disposition", "attachment; filename=" + filename); // Force 'save-as'
        ZipFile zip = new ZipFile(zipfile);
        for (Enumeration e = zip.entries(); e.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            if(entry.toString().equals(filename)) {
                InputStream is = zip.getInputStream(entry);
                BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"), 65536);
                while ((aLine = br.readLine()) != null) {
                    out.println(aLine);
                }
                is.close();
                break;
            }
        }
    }
}

Để biên dịch trên Tomcat, bạn cần có đường dẫn lớp bao gồm tomcat \ lib \ servlet-api.jar hoặc trên GlassFish: glassfish \ lib \ j2ee.jar

Nhưng một trong hai sẽ làm việc trên cả hai. Bạn cũng cần đặt servlet của bạn vào web.xml.


0

Thêm một tiêu đề phản hồi Nội dung-Bố trí: tệp đính kèm; theo sau là tên tập tin Loại bỏ nội dung Meta-Bố trí; Nội tuyến; sẽ mở tài liệu trong cùng một cửa sổ

Trong java, nó được đặt là

response.setHeader("Content-Disposition", "attachment;filename=test.jpg");

-2

Với các tệp PDF lớn, trình duyệt bị treo. Trong Mozilla, menu Công cụTùy chọnỨng dụng , sau đó bên cạnh loại nội dung tài liệu Adobe Acrobat. Trong phần thả xuống Hành động, chọn Luôn hỏi .

Điều này không làm việc cho tôi, vì vậy những gì đã làm việc là:

Công cụ trình đơn * → Tiện ích bổ sungAdobe Acrobat (plugin Adobe PDF cho Firefox) → TUYỆT VỜI. Bây giờ tôi có thể tải sách điện tử!


2
bạn đã đọc câu hỏi chưa? đây không phải là câu trả lời của trình duyệt chéo
Đánh dấu

1
@mark đó cũng là hướng dẫn cho người dùng nhắc nhở tải xuống các tệp PDF bắt buộc, không phải chủ sở hữu trang web.
Nathan Hornby
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.