php 如何使 PDF 文件可在 HTML 链接中下载?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/364946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 22:30:22  来源:igfitidea点击:

How to make PDF file downloadable in HTML link?

phppdfxhtmldownloadmarkup

提问by Prashant

I am giving link of a pdf file on my web page for download, like below

我在我的网页上提供 pdf 文件的链接以供下载,如下所示

<a href="myfile.pdf">Download Brochure</a>

The problem is when user clicks on this link then

问题是当用户点击这个链接时

  • If the user have installed Adobe Acrobat, then it opens the file in the same browser window in Adobe Reader.
  • If the Adobe Acrobat is not installed then it pop-up to the user for Downloading the file.
  • 如果用户已安装 Adob​​e Acrobat,则它会在 Adob​​e Reader 的同一浏览器窗口中打开文件。
  • 如果未安装 Adob​​e Acrobat,则会向用户弹出下载文件。

But I want it always pop-up to the user for download, irrespective of "Adobe acrobat" is installed or not.

但我希望它总是弹出给用户下载,无论是否安装了“Adobe acrobat”。

Please tell me how i can do this?

请告诉我我该怎么做?

采纳答案by TravisO

Instead of linking to the .PDF file, instead do something like

与其链接到 .PDF 文件,不如执行类似的操作

<a href="pdf_server.php?file=pdffilename">Download my eBook</a>

which outputs a custom header, opens the PDF (binary safe) and prints the data to the user's browser, then they can choose to save the PDF despite their browser settings. The pdf_server.php should look like this:

它输出自定义标题,打开 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: and obviously run some sanity checks on the "file" variable to prevent people from stealing your files such as don't accept file extensions, deny slashes, add .pdf to the value

PS:显然对“文件”变量运行一些健全性检查以防止人们窃取您的文件,例如不接受文件扩展名,拒绝斜杠,将 .pdf 添加到值中

回答by T_D

This is a common issue but few people know there's a simple HTML 5 solution:

这是一个常见问题,但很少有人知道有一个简单的 HTML 5 解决方案:

<a href="./directory/yourfile.pdf" download="newfilename">Download the pdf</a>

Where newfilenameis the suggested filename for the user to save the file. Or it will default to the filename on the serverside if you leave it empty, like this:

newfilename用户保存文件的建议文件名在哪里。或者如果您将其留空,它将默认为服务器端的文件名,如下所示:

<a href="./directory/yourfile.pdf" download>Download the pdf</a>

Compatibility: I tested this on Firefox 21 and Iron, both worked fine. It might not work on HTML5-incompatible or outdated browsers. The only browser I tested that didn't force download is IE...

兼容性:我在 Firefox 21 和 Iron 上对此进行了测试,两者都运行良好。它可能不适用于与 HTML5 不兼容或过时的浏览器。我测试过的唯一没有强制下载的浏览器是 IE...

Check compatibility here: http://caniuse.com/#feat=download

在此处检查兼容性:http: //caniuse.com/#feat=download

回答by Alex V

Don't loopthrough every file line. Use readfileinstead, its faster. This is off the php site: http://php.net/manual/en/function.readfile.php

不要遍历每个文件行。改用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;
}

Make sure to sanitize your get variable as someone could download some php files...

确保清理你的 get 变量,因为有人可以下载一些 php 文件......

回答by Rob W

Instead of using a PHP script, to read and flush the file, it's more neat to rewrite the header using .htaccess. This will keep a "nice" URL (myfile.pdfinstead of download.php?myfile).

不是使用 PHP 脚本来读取和刷新文件,而是使用.htaccess. 这将保留一个“不错”的 URL(myfile.pdf而不是download.php?myfile)。

<FilesMatch "\.pdf$">
ForceType applicaton/octet-stream
Header set Content-Disposition attachment
</FilesMatch>

回答by Alex W

I found a way to do it with plain old HTML and JavaScript/jQuery that degrades gracefully. Tested in IE7-10, Safari, Chrome, and FF:

我找到了一种使用普通旧 HTML 和 JavaScript/jQuery 优雅降级的方法。在 IE7-10、Safari、Chrome 和 FF 中测试:

HTML for download link:

下载链接的 HTML:

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

jQuery (pure JavaScript code would be more verbose) that simulates clicking on link after a small delay:

jQuery(纯 JavaScript 代码会更冗长)模拟在一小段延迟后点击链接:

var delay = 3000;
window.setTimeout(function(){$('#downloadLink')[0].click();},delay);

To make this more robust you could add HTML5 feature detection and if it's not there then use window.open()to open a new window with the file.

为了使其更健壮,您可以添加 HTML5 功能检测,如果不存在,则使用window.open()该文件打开一个新窗口。

回答by Sudden Def

This is the key:

这是关键:

header("Content-Type: application/octet-stream");

Content-type application/x-pdf-document or application/pdf is sent while sending PDF file. Adobe Reader usually sets the handler for this MIME type so browser will pass the document to Adobe Reader when any of PDF MIME types is received.

内容类型 application/x-pdf-document 或 application/pdf 在发送 PDF 文件时发送。Adobe Reader 通常会为此 MIME 类型设置处理程序,因此当接收到任何 PDF MIME 类型时,浏览器会将文档传递给 Adob​​e Reader。

回答by Shivek Parmar

I know I am very late to answer this but I found a hack to do this in javascript.

我知道我回答这个问题已经很晚了,但我发现了一个在 javascript 中做到这一点的技巧。

function downloadFile(src){
    var link=document.createElement('a');
    document.body.appendChild(link);
    link.href= src;
    link.download = '';
    link.click();
}

回答by Mark Allena

I solved mine using the whole url of the PDF file (Instead of just putting the file name or location to href): a href="domain . com/pdf/filename.pdf"

我使用 PDF 文件的整个 url 解决了我的问题(而不仅仅是将文件名或位置放在 href 中):a href="domain . com/pdf/filename.pdf"

回答by Mehran Hooshangi

if you need to limit download rate, use this code !!

如果您需要限制下载速率,请使用此代码!

<?php
$local_file = 'file.zip';
$download_file = 'name.zip';

// set the download rate limit (=> 20,5 kb/s)
$download_rate = 20.5;
if(file_exists($local_file) && is_file($local_file))
{
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($local_file));
header('Content-Disposition: filename='.$download_file);

flush();
$file = fopen($local_file, "r");
while(!feof($file))
{
    // send the current file part to the browser
    print fread($file, round($download_rate * 1024));
    // flush the content to the browser
    flush();
    // sleep one second
    sleep(1);
}
fclose($file);}
else {
die('Error: The file '.$local_file.' does not exist!');
}

?>

For more information click here

欲了解更多信息,请单击此处

回答by user11021789

<!DOCTYPE html>  
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
    <title>File Uploader</title>  
    <script src="../Script/angular1.3.8.js"></script>  
    <script src="../Script/angular-route.js"></script>  
    <script src="../UserScript/MyApp.js"></script>  
    <script src="../UserScript/FileUploder.js"></script>  
    <>  
        .percent {  
            position: absolute;  
            width: 300px;  
            height: 14px;  
            z-index: 1;  
            text-align: center;  
            font-size: 0.8em;  
            color: white;  
        }  

        .progress-bar {  
            width: 300px;  
            height: 14px;  
            border-radius: 10px;  
            border: 1px solid #CCC;  
            background-image: -webkit-gradient(linear, left top, left bottom, from(#6666cc), to(#4b4b95));  
            border-image: initial;  
        }  

        .uploaded {  
            padding: 0;  
            height: 14px;  
            border-radius: 10px;  
            background-image: -webkit-gradient(linear, left top, left bottom, from(#66cc00), to(#4b9500));  
            border-image: initial;  
        }  
    </>  
</head>  
<body ng-app="MyApp" ng-controller="FileUploder">  
    <div>  
        <table ="width:100%;border:solid;">  
            <tr>  
                <td>Select File</td>  
                <td>  
                    <input type="file" ng-model-instant id="fileToUpload" onchange="angular.element(this).scope().setFiles(this)" />  
                </td>  
            </tr>  
            <tr>  
                <td>File Size</td>  
                <td>  
                    <div ng-repeat="file in files.slice(0)">  
                        <span ng-switch="file.size > 1024*1024">  
                            <span ng-switch-when="true">{{file.size / 1024 / 1024 | number:2}} MB</span>  
                            <span ng-switch-default>{{file.size / 1024 | number:2}} kB</span>  
                        </span>  
                    </div>  
                </td>  
            </tr>             
            <tr>  
                <td>  
                    File Attach Status  
                </td>  
                <td>{{AttachStatus}}</td>  
            </tr>  
            <tr>  
                <td>  
                    <input type="button" value="Upload" ng-click="fnUpload();" />  
                </td>  
                <td>  
                    <input type="button" value="DownLoad" ng-click="fnDownLoad();" />  
                </td>  
            </tr>  
        </table>  
    </div>  
</body>  
</html>