在HTML中点击文本链接时强制打开“另存为”弹出窗口以下载PDF文件。

210

我在我的网站上有一些大型PDF目录,我需要将它们链接为下载。当我使用谷歌搜索时,我发现了下面这个方法。它应该在链接单击时打开“另存为...”弹出窗口...

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

但是它不起作用 :/ 当我按照以下方式链接到文件时,它只会链接到文件并尝试打开该文件。

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

更新(根据下面的答案):

我发现没有100%可靠的跨浏览器解决方案。可能最好的方法是使用下面列出的其中一个网页服务,并提供下载链接...


1
不要提供PDF文件的MIME类型。 - bhups
我尝试了你更新的解决方案artmania,但在Safari中仍然出现了我一直遇到的同样问题。我在浏览器窗口中看到了类似PDF的东西,只有当我点击底部的“预览”或“下载”选项卡时,才能得到我非常需要的搜索功能。 - heathwaller
如何自动强制下载PDF?你可以使用以下代码来自动强制下载PDF文件:header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="downloaded.pdf"'); readfile("path/to/your/file.pdf");请确保将“path/to/your/file.pdf”替换为您的PDF文件的实际路径。 - Ciro Santilli OurBigBook.com
将以下与编程有关的内容从英语翻译为中文。仅返回翻译后的文本:类似但不特定于文件类型:https://dev59.com/EHM_5IYBdhLWcg3wPAjT - Ciro Santilli OurBigBook.com
19个回答

303

这段内容是关于如何在浏览器中点击链接后强制保存文件的方法,来自于一个 Stack Overflow问题 的回答:

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

25
目前(留言时),download属性仅限于Chrome、Firefox和Opera浏览器使用。即使是最新版本的IE和Safari也不支持该属性。如果想要了解未来的支持情况,请查看http://caniuse.com/#feat=download! - Sygmoral
Netbeans的错误检查会抱怨它,但它似乎工作得很好。您可以像这样为新文件指定一个初步名称:download="myFile.txt"。 - Yster
2
在撰写本评论时,此方法适用于Edge,并且似乎是阻止超链接PDF在Edge的非常糟糕的PDF查看器中打开的唯一方法。 - user1641172
13
这个方法只适用于同源链接,如 https://caniuse.com/#feat=download 中所述。如果你的链接跨域,你现在唯一的选择是强制响应类型为“application/octet-stream”,就像许多答案建议的那样。如果你没有访问服务器的权限,那么你可以尝试代理它并手动设置响应头。 - jean-baptiste
1
@jean-baptiste 同意... 这是一个有点荒谬的限制,因为它极大地限制了功能,而实际上有许多方法可以规避所谓的“保护”。 - user1156544
显示剩余3条评论

98

使用download属性,但要注意它仅适用于与您的代码相同来源托管的文件。这意味着用户只能下载来自原始站点、相同主机的文件。

使用原始文件名下载:

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

使用'some_name'作为文件名进行下载:

<a href="file link" download="some_name" target="_blank">Click here to download</a>
通过添加target="_blank"属性,我们将在新标签页中打开链接,这也有助于在某些情况下正确使用download属性。此属性遵循与同源策略相同的规则。您可以在MDN Web Doc 同源策略页面了解更多信息。您还可以在MDN Web Doc 超链接属性页面了解有关此下载 HTML5 属性的更多信息。

3
虽然已经是2013年Ayush Gupta的最佳答案,但这与当前的最佳答案完全相同。然而,target="_blank"可能会使不支持的浏览器更易于使用(PDF文件将在新窗口/标签页中打开,而不是覆盖当前页面)。 - Sygmoral
3
对我来说,target="_blank"是必要的,因为在 Chrome 浏览器中,仅使用 download 无法正常触发下载。 - casraf
4
如果您在“下载”属性中提供一个字符串,它将被用作文件名。我一直在用户脚本中使用它。 - weaknespase
2
请纠正我如果我错了,但是下载并不是一个“另存为”对话框。下载和target_blank只是在新标签页中打开文件。 - RationalRabbit
仅适用于同源! - Cristian E.

37

元标签并不是一种可靠的方式来实现此目的。通常情况下,即使这样做也不应该——它应该由用户/用户代理自行决定如何处理您提供的内容。如果用户希望,他们总是可以强制他们的浏览器下载文件。

如果您仍然想强制浏览器下载文件,请直接修改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协议的一个扩展;一些浏览器可能会忽略它。

4
实际上,我认为这已被广泛实施。 - Matthew Wilson
这是最好的解决方案,无需麻烦,而且非常有效。您可以使用此方法直接下载任何文件类型。+1 - casraf
3
HTTP协议中不存在Content-Transfer-Encoding。Content-Encoding:none是无用的。 - Julian Reschke
请注意,在您的回答中注明,如果文件来自外部服务器/域,则此答案可能不是解决方案... - T.Todua
我想补充一下,当文件变得很大(>80 MB在我的情况下)时,我曾经在某些服务器上遇到过此类代码失败或类似的情况。使用 ob_end_flush() 也没有帮助。 - Hendrik
应该由用户/用户代理决定如何处理您提供的内容,这取决于您拥有哪种类型的用户。我们有员工用户,还有针对某些.pdf表格的客户,特别是打印行为在不同的浏览器中差异很大,并且与pdf阅读器应用程序的渲染方式相差很大。项目消失了,厚重的边框从空气中变出来......我们需要用户从pdf应用程序而非浏览器中打开特定的pdf。 - PoloHoleSet

25

我也遇到过这个问题,找到了一个解决方案,目前为止效果非常好。将以下代码放入你的.htaccess文件中:

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

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


4
这个方法很有效,因为我有一个专门用于下载的文档目录。我省略了ForceType,只是让文件类型保持不变。我也不需要大小写不敏感;我的系统似乎已经是大小写不敏感的了。我添加了一些额外的文件类型,包括可选的旧/新办公室扩展名:"<FilesMatch ".(pdf|xlsx?|docx?)$">"。 - goodeye
这个方法非常有效,甚至在OSX Safari中也能正常工作,而其他答案(包括被接受的答案,正如一位评论者指出的那样)只能在支持给定HTML功能的某些浏览器上使用。对我来说,这个方法似乎更理想,因为它可以跨越所有浏览器平台运行,但需要更高级别的访问服务器配置文件的权限。 - bwright
你也可以把它直接放在你的apache.conf文件中,我不使用.htaccess因为它需要更多的资源。 - Michael Fever
一个托管在Windows上的网站如何实现这个功能,因为它们无法读取htaccess文件? - PoloHoleSet

12

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

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

2
@Martin 在 Chrome OS 上使用 Chrome,而在 Linux 上使用 Firefox。结果发现文件需要本地才能正常工作。我的 href 是指向云存储的 URL。 - ttfreeman

7

通常情况下,这是因为一些浏览器的设置或插件直接在同一个窗口中像简单的网页一样打开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: <br /><em>$file</em></h1>";
    }
?>

将上述内容保存为download.php
将此小片段保存为PHP文件,并在服务器上的某个位置使用它,您可以使用它在浏览器中下载文件,而不是直接显示。如果要提供PDF以外的文件,请删除或编辑第5行。
您可以像这样使用它:
将以下链接添加到您的HTML文件中。
<a href="download.php?file=my_pdf_file.pdf">Download the cool PDF.</a>

参考来源:这篇博客


9
这似乎是一种不错的方法,可以将服务器上的每个文件提供给任何留意的人。例如,download.php?file=database_password_file.php - pbarney

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

AddType application/octet-stream .pdf

我希望它能够像它现在一样独立于浏览器。

我很想知道为什么这个被downvote了 - 这是最简单的方法之一,而且有效:https://css-tricks.com/snippets/htaccess/force-files-to-download-not-open-in-browser/ - Nathan Hornby
人们试图在免费的托管网站上修改服务器的核心功能,然后因为无法使其工作而进行投票。其他每个解决方案都会有缺点,因为这是“黑客”替代它的方法。 - Abandoned Cart
我会给它点踩,因为这不是解决问题的正确方法。改变资源类型是个坏主意。 - Brad
@NathanHornby - 我没有给它投反对票,但是这对于任何托管在Windows上的网站都不起作用,因为它们不使用 .htaccess。 - PoloHoleSet
我没有点踩,但这个解决方案盲目地影响了该后缀的所有文件。它是不加区分的,因此并不适用于所有情况。 - JBH
它可能与浏览器无关,但它不是依赖于Web服务器是[Apache](http://en.wikipedia.org/wiki/Apache_HTTP_Server)吗? - Peter Mortensen

7

我刚使用了这个功能,但不确定它是否适用于所有浏览器。

在 Firefox 浏览器中可用:

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

3
建议参考早期回答,其中包含更多背景信息。 - Jongware

5

只需将以下代码放入您的.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);

1
这不是假定Web服务器是Apache吗? - Peter Mortensen

5
一个十分简单的方法,无需使用外部下载网站或修改头文件等,只需要创建一个ZIP文件,并在其中嵌入PDF文件,并直接链接到该ZIP文件。这样做将总是触发保存/打开对话框,而且对于人们来说双击PDF文件仍然很容易,因为与.zip相关联的程序会自动启动。顺便说一句,这是一个很好的问题,我也一直在寻找答案,因为大多数浏览器内嵌的PDF插件需要很长时间才能显示任何东西(并且通常会在PDF加载时挂起浏览器)。

35
糟糕的可用性。许多终端用户不知道如何处理压缩文件。 - CodeWarrior
1
有时候,简单的解决方案是最好的解决方案! - elrado
1
不是一个好的解决方案。我在Firefox和ZIP文件中正好遇到了这个问题。我该怎么办?压缩文件?在这种情况下,修改HTTP头可能是一个解决方案,但我无法访问它。 - Arnaud Weil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接