首页 文章

强制打开“另存为...”弹出窗口打开文本链接单击 HTML 中的 PDF

提问于
浏览
157

我的网站上有一些大尺寸的 PDF 目录,我需要将它们作为下载链接。当我用 Google 搜索时,我发现下面有这样的事情。它应该在链接点击时打开“另存为...”弹出窗口...

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

但它不起作用:/当我链接到如下文件时,它只是链接到文件,并试图打开该文件。

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

更新(根据以下答案):

我认为没有 100%可靠的 cross-browser 解决方案。可能最好的方法是使用下面列出的一个 Web 服务,并提供下载链接...

17 回答

  • 239

    从答案到单击链接后强制浏览器保存文件

    <a href="path/to/file" download>Click here to download</a>
    
  • 77
    <a href="file link" download target="_blank">Click here to download</a>
    

    它适用于 Firefox 和 Chrome。

  • 33

    元标记不是实现此结果的可靠方法。一般情况下,您甚至不应该这样做 - 应由 user/user 代理人决定如何处理您提供的内容。用户可以随时强制他们的浏览器下载文件。

    如果您仍想强制浏览器下载文件,请直接修改 HTTP 标头。这是一个 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
    

    请注意,这只是 HTTP 协议的扩展;有些浏览器可能会忽略它。

  • 22

    我遇到了同样的问题,并找到了迄今为止效果很好的解决方案。您将以下代码放在.htaccess文件中:

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

    它来自强制下载文件而不是在浏览器中显示

  • 9

    我发现了一个非常简单的 Firefox 解决方案(仅适用于相对而不是直接 href):添加type="application/octet-stream"

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

    通常它会发生,因为某些浏览器设置或 plug-ins 直接在同一个窗口中打开 PDF 就像一个简单的网页。

    以下内容对您有所帮助。几年前我用 PHP 完成了它。但目前我还没有在那个平台上工作。

    <?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: 
    <em>$file</em></h1>"; } ?>

    将上面保存为 download.php。

    将这个小片段保存为服务器上的某个 PHP 文件,您可以使用它在浏览器中下载文件,而不是直接显示。如果要提供 PDF 以外的文件,请删除或编辑第 5 行。

    您可以像这样使用它:

    将以下链接添加到 HTML 文件中。

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

    参考来自:这个博客

  • 5

    尝试将此行添加到.htaccess 文件中。

    AddType application/octet-stream .pdf
    

    我希望它能够工作,因为它独立于浏览器。

  • 4

    只需将以下代码放在.htaccess文件中:

    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
    

    或者您也可以通过 JavaScript 进行操作

    element.setAttribute( 'download', whatever_string_you_want);
    
  • 4

    我刚刚使用过这个,但我不知道它是否适用于所有浏览器。

    它适用于 Firefox:

    <a href="myfile.pdf" download>Click to Download</a>
    
  • 3

    实现这一目的的一种非常简单的方法,不使用外部下载站点或修改标题等,只需创建一个包含 PDF 的 ZIP 文件,并直接链接到 ZIP 文件。这将始终触发 Save/Open 对话框,并且人们仍然可以轻松地启动与.zip 相关联的程序的 PDF 窗口。

    BTW 很好的问题,我也在寻找答案,因为大多数 browser-embedded PDF 插件都需要很长时间来显示任何内容(并且在加载 PDF 时经常挂起浏览器)。

  • 3

    如果您需要强制下载页面上的单个链接,一种非常简单的方法是使用 href-link 中的 HTML5 download-attribute。

    见:http://davidwalsh.name/download-attribute

    使用此功能,您可以重命名用户将下载的文件,同时强制下载。

    关于这是否是一个好的做法一直存在争议,但在我的情况下,我有一个 pdf 文件的嵌入式查看器,并且查看器不提供下载链接,所以我必须单独提供一个。在这里,我想确保用户没有在 Web 浏览器中打开 pdf,这会令人困惑。

    这不需要打开保存 as-dialog,但会直接将链接下载到预设下载目的地。当然,如果你为别人做一个网站,并且需要他们手动将属性写入他们的链接可能是一个坏主意,但如果有办法将属性放入链接,这可能是一个轻松的解决方案。

  • 2

    在所有浏览器中实现“download”属性之前,server-side 解决方案更兼容。

    一个 Python 示例可以是文件存储的自定义 HTTP 请求处理程序。指向文件存储的链接生成如下:

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

    这是代码:

    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()
    
  • 0

    在 HTML 代码中的文件名之后我添加了?forcedownload=1

    这是我触发保存或下载对话框的最简单方法。

  • 0

    如果您在浏览器中有一个知道如何打开 PDF 文件的插件,它将直接打开。就像图像和 HTML 内容一样。

    因此,替代方法不是在响应中发送您的 MIME 类型。通过这种方式,浏览器永远不会知道哪个插件应该打开它。因此它会给你一个 Save/Open 对话框。

  • 0

    我刚才有一个非常类似的问题,我需要创建 ZIP 文件中文件的下载链接。

    我首先尝试创建一个临时文件,然后提供了一个临时文件的链接,但我发现有些浏览器只显示内容(CSV Excel 文件)而不是提供下载。最终我通过使用 servlet 找到了解决方案。它适用于 Tomcat 和 GlassFish,我在 Internet Explorer 10 和 Chrome 上尝试过。

    servlet 将 ZIP 文件的完整路径名称作为输入,以及应下载的 zip 文件的名称。

    在我的 JSP 文件中,我有一个表格,显示 zip 中的所有文件,链接说:onclick='download?zip=<%=zip%>&csv=<%=csv%>'

    servlet 代码在 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;
                }
            }
        }
    }
    

    要在 Tomcat 上编译,您需要包含 tomcat\lib\servlet-api.jar 或在 GlassFish 上的类路径:glassfish\lib\j2ee.jar

    但是任何一个都可以兼顾。您还需要在web.xml中设置 servlet。

  • 0

    这是旧帖子,但这里是我使用 jQuery 库的 JavaScript 解决方案。

    <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>
    

    您只需要在<a>标记内使用类force-download并自动强制下载。您也可以将其添加到父div并将其中的所有链接都获取。

    例:

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

    这对 WordPress 和任何其他系统或自定义网站都很有用。

  • -2

    对于大型 PDF 文件,浏览器会挂起。在 Mozilla 中,菜单工具→选项→应用程序,然后在内容类型 Adobe Acrobat 文档旁边。在“操作”下拉列表中,选择“始终询问”。

    这对我没用,所以有用的是:

    菜单工具*→Add-ons→Adobe Acrobat(适用于 Firefox 的 Adobe PDF 插件)→禁用。现在我可以下载 e-books 了!

相关问题