我在网页上提供了一个PDF文件的下载链接,如下所示:
<a href="myfile.pdf">Download Brochure</a>
问题是当用户单击此链接时,
- 如果用户已安装Adobe Acrobat,则在Adobe Reader中的同一浏览器窗口中打开文件。
- 如果未安装Adobe Acrobat,则弹出下载文件的提示框。
但我希望它始终弹出下载提示框,无论"Adobe Acrobat"是否安装。
请告诉我如何实现这个功能?
这是一个常见的问题,但很少有人知道有一个简单的HTML 5解决方案:
<a href="./directory/yourfile.pdf" download="newfilename">Download the pdf</a>
其中newfilename
是建议用户保存该文件时使用的文件名。如果您将其留空,它将使用服务器端上的文件名作为默认文件名:
<a href="./directory/yourfile.pdf" download>Download the pdf</a>
兼容性:我已在Firefox 21和Iron上测试过,均正常工作。它可能不适用于不支持HTML5或过时的浏览器。我测试的唯一一个未强制下载的浏览器是IE...
在这里检查兼容性:http://caniuse.com/#feat=download
不要链接至 PDF 文件,而是尝试使用以下方式
<a href="pdf_server.php?file=pdffilename">Download my eBook</a>
这段代码会输出一个自定义的头部,打开PDF(二进制安全),并将数据打印到用户的浏览器上,然后用户可以选择保存PDF文件,即使他们的浏览器设置不允许。pdf_server.php应该长这样:
header("Content-Type: application/octet-stream");
$file = $_GET["file"] .".pdf";
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize($file));
flush(); // this doesn't really matter.
$fp = fopen($file, "r");
while (!feof($fp))
{
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
PS:显然需要对“file”变量进行一些合理性检查,以防止人们窃取您的文件,例如不接受文件扩展名、拒绝斜杠,并将.pdf添加到值中。
fopen
,从而引入严重的LFI漏洞。 - Joost不要使用循环遍历每一行文件。 使用readfile函数代替,它更快。这是从php网站上获取的信息: http://php.net/manual/en/function.readfile.php
$file = $_GET["file"];
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=' . urlencode(basename($file)));
// header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
一定要对您的get变量进行清理,因为有人可能会下载一些php文件...
使用.htaccess
重写头部信息比使用PHP脚本来读取和刷新文件更简洁。这样可以使URL更美观(例如:myfile.pdf
而不是download.php?myfile
)。
<FilesMatch "\.pdf$">
ForceType applicaton/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
<p>Thanks for downloading! If your download doesn't start shortly,
<a id="downloadLink" href="...yourpdf.pdf" target="_blank"
type="application/octet-stream" download="yourpdf.pdf">click here</a>.</p>
var delay = 3000;
window.setTimeout(function(){$('#downloadLink')[0].click();},delay);
window.open()
打开一个新窗口并显示文件。header("Content-Type: application/octet-stream");
<a href="myfile.pdf">Download Brochure</a>
<a href="myfile.pdf" download>Download Brochure</a>
为下载属性指定一个值:
<a href="myfile.pdf" download="Brochure">Download Brochure</a>
这里的文件名将是Brochure.pdf。
我知道回答已经很晚了,但我发现了一种用JavaScript实现的技巧。
function downloadFile(src){
var link=document.createElement('a');
document.body.appendChild(link);
link.href= src;
link.download = '';
link.click();
}
尝试这个:
<a href="pdf_server_with_path.php?file=pdffilename&path=http://myurl.com/mypath/">下载我的电子书</a>
pdf_server_with_path.php 中的代码是:
header("Content-Type: application/octet-stream");
$file = $_GET["file"] .".pdf";
$path = $_GET["path"];
$fullfile = $path.$file;
header("Content-Disposition: attachment; filename=" . Urlencode($file));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . Filesize($fullfile));
flush(); // this doesn't really matter.
$fp = fopen($fullfile, "r");
while (!feof($fp))
{
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
<FilesMatch "\.(?i:pdf)$">
Header set Content-Disposition attachment
</FilesMatch>
FilesMatch指令只是一个正则表达式,因此可以设置得非常细致,或者您可以添加其他扩展名。
Header行与上面的PHP脚本中的第一行执行相同的操作。如果您还需要设置Content-Type行,可以以相同的方式进行设置,但我发现这并不必要。