(HTML)下载PDF文件,而不是单击时在浏览器中打开它们


114

我想知道如何使PDF文件链接可下载,而不是在浏览器中打开它们?如何在html中完成?(我认为这是通过javascript或其他方式完成的)。


3
据我所知,这不是脚本行为。大多数浏览器将针对下载特定文件类型的行为具有自己的设置。
巴特

1
从HTML5开始,OP应该将正确的答案更新为Sarim的答案。
奥马尔·塔里克

力的可能重复项,以打开“另存为...”弹出
框,

这个问题在这里也得到了回答: stackoverflow.com/a/30714824/847235
intrepidis 2015年

Answers:


38

您无法使用HTML执行此操作。这是基于服务器的解决方案。您必须流式传输文件,以便浏览器触发保存对话框。

我建议不要这样做。用户如何与PDF交互应由用户决定。

更新(2014):

所以...这个答案仍然有很多不足之处。我认为部分原因是4年前已经回答过,正如Sarim指出的那样,现在有HTML 5 download属性可以处理此问题。

我同意,并且认为Sarim的答案很好(如果OP回来的话,应该是选择的答案)。但是,此答案仍然是处理该问题的可靠方法(正如YiğitYener的答案指出的,而且-令人感到奇怪-人们对此表示赞同)。尽管download属性获得了支持,但仍然参差不齐:

http://caniuse.com/#feat=download


18
我知道这一岁-但我不同意。在某些情况下,强制执行此行为对于应用程序流非常重要。实际的答案是将标题中的content-Disposition设置为“ attachment”而不是“ inline”。
2012年

9
我同意在其他情况下,最好由用户控制。但是,我来到此线程中寻找答案,而选中的“答案”不是答案-它是“您不应该这样做。”对我来说,这不是问题的答案,而是给出一个具体的答案并提供建议
user158017

1
有时这个问题是错误的。;)无论如何,关于您的问题,这全都是UX问题。有时有必要强制Web以特定方式运行,但是从UX角度来看,通常存在更好的解决方案。另外,我的回答是正确的。您无法使用HTML来完成您想做的事情(这就是问题所在)。作为服务器端解决方案。
DA。

1
这是我有史以来最怪异的答案之一。人们仍然在这里找到自己的方式来投票。没关系!但是知道为什么会很有趣。
DA。

3
关于这种低落的投票,可能是文明的垮台,在文本中无意中看到了多么容易。只要有光顾的意见,而缺少答案,这个答案就会使我印象深刻。代替第1款,只需将http标签添加到问题中即可。而不是第2段:“您可能要重新考虑是否阻止即时查看PDF对所有用户都是最大的利益。话虽如此……”然后假设OP和未来的读者已经成年,然后继续寻求可行的答案,例如Yener's
鲍勃·斯坦

133

使用html5,现在有可能。在元素中设置一个“下载”属性。

<a href="http://link/to/file" download="FileName">Download it!</a>

来源:http : //updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download


如果支持,则最好使用此解决方案。这是一种检查方法的方法if ("download" in document.createElement("a")){ ... }
pmrotule 2015年

我在下面添加了另一个答案(尽管是严重的hack),尽管这仍然是首选方法,但也许可以为不受支持的浏览器提供hack方法。
萨里姆

有没有一种方法可以为pdf指定文本而不是提及文件路径?我需要从div html创建pdf,但是我不希望打开另一个窗口,下载应该像这个答案一样
。.– T.Adak

1
截至2019年8月,此功能似乎已增强了浏览器支持,请参阅:w3schools.com/tags/att_a_download.asp
Daniel Resch

2
请注意,仅同源来源的请求才支持download属性。
昆汀

82

只有通过服务器端代码设置http响应标头才有可能。即

Content-Disposition: attachment; filename=fname.ext

2
这是一个完美的答案-只需找到使用适当的服务器端语言进行操作的方法即可。
2012年

Apache示例。烧瓶的例子。
鲍勃·斯坦

不幸的是,即使内容配置为“附件”,iOS仍将预览并且不会下载pdf文件。
乔恩·范·德·贝克

14

您需要更改发送的http标头。根据服务器的不同,您可以如下修改.htaccess:

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

内容类型无需撒谎。设置内容配置就足够了。
昆汀

9

您将需要使用PHP脚本(或其他服务器端语言)

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?>

并使用httacces重定向(重写)到PHP文件而不是pdf


嗯,当我直接打开php文件时,效果很好。但是,当我尝试使用重定向时,例如这里:Redirect 301 /_PDFs/Catalogue.pdf http://www.example.com/_PDFs/___download_the_catalogue_instead_opening.php并尝试打开pdf文件,它仍然会在浏览器中打开原始文件,而不是下载重命名的版本...
ellockie

更新:当没有文件被直接调用时(在我的示例中为“ Catalogue.pdf”),它可以工作。这样重定向就可以完美地工作了。谢谢!
ellockie

8

您可以使用

Response.AddHeader("Content-disposition", "attachment; filename=" + Name);

看看这个例子:

http://www.codeproject.com/KB/aspnet/textfile.aspx

这适用于ASP.NET。我相信您可以在所有其他服务器端语言中找到类似的解决方案。但是,就我所知,还没有JavaScript解决方案。


这就是答案(以及与PHP相关的答案)。关键是必须对http响应标头进行编辑。
2012年

5

没有html5属性,可以使用php来实现:

使用以下代码创建名为download.php的 php文件:

<?php
ob_start();
$file = "yourPDF.pdf"

if (file_exists($file)) 
{
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit();
}

现在,如果您要自动开始下载pdf,请编写以下javascript:

<script>window.location = "download.php";</script>

如果您希望它在链接上起作用,请使用此...

<a href='javascript:window.location = "download.php"'>
    Download it!
</a>

4
请注意,使用URL参数进行此操作时需要小心。例如$file = $_GET['$file'];。因为然后一个人也可以呼叫download.php?file=../../../wp-config.php或其他任何给定资源。额外检查扩展名,MIME类型和允许的下载路径(并剥离“ ../”之类的东西)非常重要!
Giel Berkers,2015年

是我还是做<a href='javascript...'>与直接将链接放入<a href='download.php'> ?
allan.simon

5

当您想直接从浏览器下载任何图像或pdf文件时,而不是在新标签页中打开它时,则在javascript中,您应该将值设置为创建动态链接的下载属性

    var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    var event = document.createEvent('Event');
    event.initEvent('click', true, true); 
    save.dispatchEvent(event);
   (window.URL || window.webkitURL).revokeObjectURL(save.href);

对于新的Chrome更新,某些时间事件不起作用。对于以下代码将被使用

  var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    document.body.appendChild(save);
    save.click();
    document.body.removeChild(save);

追加子项和删除子项仅对Firefox(仅Internet Explorer浏览器)有用。在chrome上,无需附加和删除子项即可使用


2

最适合我的解决方案是Nick在他的博客上撰写的解决方案

他的解决方案的基本思想是使用Apache服务器标头mod并编辑.htaccess以包含FileMatch指令,该指令强制所有* .pdf文件充当流而不是附件。尽管这实际上并不涉及编辑HTML(按照原始问题),但它本身不需要任何编程。

我喜欢Nick的方法的第一个原因是因为它允许我基于每个文件夹进行设置,因此仍可以在浏览器中打开一个文件夹中的PDF,同时允许其他文件夹(我们希望用户编辑然后重新上传的PDF)被迫下载。

我还想补充一点,PDF有一个选项,可以通过API向您的服务器发布/提交可填写的表单,但这需要一段时间才能实现。

第二个原因是因为时间是考虑因素。编写PHP文件处理程序以强制header()中的内容处理也将比API花费更少的时间,但仍比Nick的方法花费更长的时间。

如果您知道如何打开Apache mod并编辑.htaccss,则可以在大约10分钟内获得此信息。它需要Linux托管(不是Windows)。这可能不适用于所有用途,因为它需要高级服务器访问权限才能进行配置。因此,如果您说过访问权限,可能是因为您已经知道如何做这两件事。如果没有,请查看Nick的博客以获取更多说明。


2

由于html5方式(我以前的回答)并非在所有浏览器中都可用,因此这是另一种稍微有点破解的方式。

此解决方案要求您从同一域提供预期的文件,或者具有CORS权限。

  1. 首先通过XMLHttpRequest(Ajax)下载文件的内容。
  2. 然后通过base64对文件内容进行编码来创建数据URI,并将media-type设置为application/octet-stream。结果应该看起来像

data:application/octet-stream;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

现在设置location.href = data。这将导致浏览器下载文件。不幸的是,您不能通过这种方式设置文件名或扩展名。摆弄媒体类型可能会产生一些效果。

查看详细信息:https : //developer.mozilla.org/zh-CN/docs/Web/HTTP/data_URIs



1

如果您使用的是HTML5(我想现在每个人都在使用HTML5),则有一个名为的属性download

例如 <a href="somepathto.pdf" download="filename">

filename是可选的,但如果提供的话,它将以此名称表示下载的文件。


可悲的是,我不得不承认我太愚蠢,无法理解这个标签。我提出了这个:<a href="download/Curriculum_it.pdf.zip">Download curriculum</a>或那个:<a href="download/Curriculum_it.pdf.zip" download="Curriculum_it">Download curriculum</a>我绝对看不出它的工作原理有什么不同。都下载我的.zip。在第二个文件中,使用filename选项似乎根本不起作用。
Garavani 2015年

0

行为应取决于如何设置浏览器以处理各种MIME类型。在这种情况下,MIME类型为application / pdf。如果要强制浏览器下载文件,可以尝试在PDF文件上强制使用其他MIME类型。我建议不要这样做,因为用户应该选择打开PDF文件时会发生什么。



-1

终于我找到了……创建动态锚标记并单击它

<script> 
   $('#myclick').click(function(){
       $('body').append('<a id="link" href="mypdf.pdf" 
        download="Payment.pdf">&nbsp;</a>');
       $('#link')[0].click();
   });
</script>

“ Payment.pdf”仅用于自定义名称。


无需动态生成链接。
昆汀

请注意,仅同源来源的请求才支持download属性。
昆汀

这似乎是同样的答案,这一个从三年前。
昆汀
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.