如何创建不需要右键单击的 PDF 下载链接?

发布于 2024-08-14 15:42:33 字数 368 浏览 3 评论 0原文

我正在开发一个网站,访问者应该能够下载 pdf 文件。 (有三个链接可供选择,但这无关紧要) 我想知道如何做到这一点,以便访问者只需单击链接即可,而不必

right click > Save (target) As...

我对 PHP 和/或 Javascript 解决方案持开放态度。谢谢。

编辑:我可以使用 javascript 调用 PHP 并通过 AJAX 保存文件吗?

EDIT2:我最终使用了 Nirmal 的解决方案,因为它对于所有三个文件来说是最简单的更改。我不需要为三个 PDF 制作 3 个文件,也不需要手动编写开关代码。 BalusC 得到了检查,因为他/她的代码首先启动并且也完成了任务。

I am working on a website where the visitor should be able to download a pdf file.
(There are three links to choose from but that is irrelevant)
I wanted to know how to make it so that the visitor can simply click the link and not have to

right click > Save (target) As...

I am open to PHP and or Javascript solutions. Thanks.

EDIT: Can I use javascript to call the PHP and save the file via AJAX?

EDIT2: I used Nirmal's solution in the end, since it was the simplest to change for all three files. I didn't need to make 3 files for the three PDF's and I didn't need to hand code the switch. BalusC gets the check though since his/her code was up first and does the trick too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

垂暮老矣 2024-08-21 15:42:33

您基本上需要做的就是设置 Content-配置标头到附件以获得“另存为”对话框。这是一个 PHP 启动示例:

<?php
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment;filename="foo.pdf"');
    readfile('/path/to/foo.pdf');
?>

您不能也不想使用 Javascript 来执行此操作。

重要提示:由于功能较差,在 MSIE 中,“另存为”对话框中的默认文件名不会从 content-disposition 标头中派生,而是作为路径信息的最后一部分请求网址。要解决此问题,请将 PDF 文件名附加到链接,例如 http://example.com/pdf/foo.pdf。您甚至可以在 PHP 中使用它来读取 pathinfo 中指定的 PDF 文件。以下是 pdf.php 的基本示例:

<?php
    $file_name = $_SERVER['PATH_INFO'];
    $file = '/path/to/pdf/files' . $file_name;
    if (file_exists($file)) {
        header('Content-Type: application/pdf');
        header('Content-Disposition: attachment;filename="' . basename($file_name) . '"');
        header('Content-Length: ' . filesize($file));
        readfile($file);
    } else {
        header('HTTP/1.1 404 Not Found');
    }
?>

但是,这假设您已打开 MultiViews,以便 /pdf/ 将浏览此 PHP 文件,或至少一个从 /pdf//pdf.php/RewriteRule

这种方法的主要优点是,每当您想要添加新的 PDF 文件或更改 PDF 文件名时,都不需要更改代码。

您甚至可以通过自动确定和设置正确的内容类型来使其更加通用:

<?php
    $file_name = $_SERVER['PATH_INFO'];
    $file = '/path/to/all/files' . $file_name;
    if (file_exists($file)) {
        header('Content-Type: ' . mime_content_type($file_name));
        header('Content-Disposition: attachment;filename="' . basename($file_name) . '"');
        header('Content-Length: ' . filesize($file));
        readfile($file);
    } else {
        header('HTTP/1.1 404 Not Found');
    }
?>

将其命名为 files.php 左右,然后您就拥有了一个通用的 PHP 下载器,您可以通过例如 http 访问它://example.com/files/foo.pdfhttp://example.com/files/bar.zip,等等。

希望这有帮助。

All you basically need to do is to set the Content-Disposition header to attachment to get a 'Save As' dialogue. Here's a kickoff PHP example:

<?php
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment;filename="foo.pdf"');
    readfile('/path/to/foo.pdf');
?>

You can't and don't want to do this with Javascript.

Important note: due to a poor feature, in MSIE the default filename in 'Save As' dialogue won't be derived from the content-disposition header, it will instead be the last part of the pathinfo in the request URL. To workaround this, append the PDF filename to the link, e.g. http://example.com/pdf/foo.pdf. You can even make use of it in PHP to read the in the pathinfo specified PDF file. Here's a basic example of pdf.php:

<?php
    $file_name = $_SERVER['PATH_INFO'];
    $file = '/path/to/pdf/files' . $file_name;
    if (file_exists($file)) {
        header('Content-Type: application/pdf');
        header('Content-Disposition: attachment;filename="' . basename($file_name) . '"');
        header('Content-Length: ' . filesize($file));
        readfile($file);
    } else {
        header('HTTP/1.1 404 Not Found');
    }
?>

This however assumes that you've MultiViews on so that /pdf/ will go through this PHP file, or at least a RewriteRule from /pdf/ to /pdf.php/.

The major advantage of this approach is that you don't need to change the code whenever you want to add a new PDF file or change the PDF file name.

You can even make it more generic by automatically determining and setting the correct content type:

<?php
    $file_name = $_SERVER['PATH_INFO'];
    $file = '/path/to/all/files' . $file_name;
    if (file_exists($file)) {
        header('Content-Type: ' . mime_content_type($file_name));
        header('Content-Disposition: attachment;filename="' . basename($file_name) . '"');
        header('Content-Length: ' . filesize($file));
        readfile($file);
    } else {
        header('HTTP/1.1 404 Not Found');
    }
?>

Name it files.php or so and then you have a generic PHP downloader which you can access by for example http://example.com/files/foo.pdf, http://example.com/files/bar.zip, etcetera.

Hope this helps.

一绘本一梦想 2024-08-21 15:42:33

如果您使用 Apache,您可以使用包含 PDF 的文件夹中的 .htaccess 文件来执行此操作,而不必编写 PHP 包装器脚本:

<Files *.pdf>
  Header set Content-Disposition attachment
</Files>

显然,某些版本的 IE / Adob​​e Reader 不遵守 Content-Disposition 标头。您可以使用 ForceType application/octet-stream 解决这些问题

<Files *.pdf>
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</Files>

Rather than having to write PHP wrapper scripts, if you are using Apache, you can do this with a .htaccess file in the folder containing the PDFs:

<Files *.pdf>
  Header set Content-Disposition attachment
</Files>

Apparently some versions of IE / Adobe Reader don't respect the Content-Disposition header. You can work around these with ForceType application/octet-stream

<Files *.pdf>
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</Files>
旧人哭 2024-08-21 15:42:33

如果您不想弄乱服务器端代码,并且这对您来说优先级较低,则可以使用 HTML5 download 属性。

示例:

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

但是并非所有浏览器都支持此功能。根据 w3schools,支持以下浏览器:

Chrome (14+)、Firefox(20+) )、歌剧 (15+)。

您还可以通过为下载属性指定值来指定文件名:

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

If you don't want to mess with server side code and if this is a low priority thing for you, you can use HTML5 download attribute.

Example:

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

However this is not supported by all browser. As per w3schools, following browsers are supported:

Chrome (14+), Firefox(20+), Opera (15+).

You can also specify filename by giving value to download attr:

<a href="myfile.pdf" download="NewName.pdf">Download</a>
国产ˉ祖宗 2024-08-21 15:42:33

尝试使用 PHP 来提供文件,同时首先发送 Content-type: application/octet-stream 标头。

Try using PHP to serve the file while first sending a header of Content-type: application/octet-stream.

我也只是我 2024-08-21 15:42:33

您可以添加 HTTP 标头来执行此操作,PHP 文档中有一个示例(参见示例一)

You can add an HTTP header to do that, there is an example in the PHP Docs (See example one)

爱殇璃 2024-08-21 15:42:33

以下代码可能会帮助您:

<?php
if(isset($_GET['docid'])){
    switch($_GET['docid']){
        case '1':
            $file = 'complete/path/to/pdf/file1';
            break;
        case '2':
            $file = 'complete/path/to/pdf/file2';
            break;
        case '3':
            $file = 'complete/path/to/pdf/file3';
            break;
        default:
            exit;
    }

    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, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
        readfile($file);
        exit;
    }
}

将此代码保存为 php 文件(例如 download.php)并从链接调用它。该脚本的作用是读取 pdf 文件并将其输出到缓冲区。标头将强制配置为下载。

要调用第一个 pdf,请 href 到“/path/to/download.php?docid=1”
要调用第二个 pdf,请 href 到“/path/to/download.php?docid=2”
要调用第三个 pdf,请 href '/path/to/download.php?docid=3'

因此,您不需要 AJAX 来完成这项工作。

The following code may help you:

<?php
if(isset($_GET['docid'])){
    switch($_GET['docid']){
        case '1':
            $file = 'complete/path/to/pdf/file1';
            break;
        case '2':
            $file = 'complete/path/to/pdf/file2';
            break;
        case '3':
            $file = 'complete/path/to/pdf/file3';
            break;
        default:
            exit;
    }

    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, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
        readfile($file);
        exit;
    }
}

Save this code as a php file (say, download.php) and call it from the link. What the script does is that it reads the pdf file and outputs it to the buffer. The headers will force the disposition as download.

To call the first pdf, href to '/path/to/download.php?docid=1'
To call the second pdf, href to '/path/to/download.php?docid=2'
To call the third pdf, href to '/path/to/download.php?docid=3'

So, you don't need AJAX to do the work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文