正确的pdf文件的PHP标头下载


78

当用户单击链接时,我真的很难让我的应用程序打开pdf。

到目前为止,anchor标签重定向到发送标头的页面:

$filename='./pdf/jobs/pdffile.pdf;

$url_download = BASE_URL . RELATIVE_PATH . $filename;

header("Content-type:application/pdf");
header("Content-Disposition:inline;filename='$filename");
readfile("downloaded.pdf");

这似乎不起作用,过去有人成功解决过此问题吗?


1
错别字?尝试' $filename='./pdf/jobs/pdffile.pdf';在该行中添加和,header("Content-Disposition:inline;filename='$filename");不要使用引号。
Funk 40 Niner,

您如何/为什么使用$url_download
Funk 40 Niner,

Answers:


135

w3schools上的示例2显示了您要实现的目标。

<?php
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");
?>

还请记住,

重要的是要注意必须在发送任何实际输出之前调用header()(在PHP 4和更高版本中,可以使用输出缓冲来解决此问题)


哈哈是真的。我之所以提到它,只是因为它有相同的例子。
2013年

输出通知加1。
iamdash

5
记住要删除文件名周围的单引号。如果您使用filename ='downloaded.pdf',则某些浏览器将尝试使用文件名中的引号保存文件。我最近在OSX上经历了这种情况。
mattis

readfile()对于大文件来说非常糟糕,因为当某些用户想要下载时,每个下载文件都在服务器ram上缓存!!!
mghhgm

1
为什么在地球上PDF会有HTML标签?
delboy1978uk

29
$name = 'file.pdf';
//file_get_contents is standard function
$content = file_get_contents($name);
header('Content-Type: application/pdf');
header('Content-Length: '.strlen( $content ));
header('Content-disposition: inline; filename="' . $name . '"');
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
echo $content;

1
请注意,将整个文件内容加载到变量中可能会与内存限制冲突。这就是为什么readfile()首选的解决方案。
Havenard

10

您的代码中需要考虑一些事项。

首先,正确编写这些标题。您将永远不会看到任何服务器正在发送Content-type:application/pdf,标题是Content-Type: application/pdf,以大写的首字母等隔开。

其中Content-Disposition的文件名仅是文件名,而不是文件的完整路径,尽管我不知道它是否是强制性的,但该名称用" not包装'。另外,您的最后一个'丢失了。

Content-Disposition: inline表示该文件应显示而不是下载。使用attachment代替。

另外,将文件扩展名大写以使其与某些移动设备兼容。(更新:可以肯定只有黑莓出现了这个问题,但是世界已经从那开始发展了,所以这不再是一个问题)

话虽如此,您的代码应该看起来像这样:

<?php

    $filename = './pdf/jobs/pdffile.pdf';

    $fileinfo = pathinfo($filename);
    $sendname = $fileinfo['filename'] . '.' . strtoupper($fileinfo['extension']);

    header('Content-Type: application/pdf');
    header("Content-Disposition: attachment; filename=\"$sendname\"");
    header('Content-Length: ' . filesize($filename));
    readfile($filename);

Content-Length是可选的,但对于希望用户能够跟踪下载进度并检测下载是否中断的情况也很重要。但是使用它时,必须确保不会随文件数据一起发送任何内容。确保之前<?php或之后绝对没有任何内容?>,甚至没有空行。


3
您不需要结束标记?>。在这种情况下,最好将其删除。
Marcel Korpel 2013年

完全可以肯定,将标头提供的文件名括在单引号中会全面破坏下载,因此,正如您所建议的那样,这有很大的不同。
布赖恩C

4

最近我遇到了同样的问题,这对我有帮助:

    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Disposition: attachment; filename="FILENAME"'); 
    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("PATH/TO/FILE")); 
    ob_clean(); 
    flush(); 
    readfile(PATH/TO/FILE);      
    exit();

我在这里找到了这个答案


2
ob_start(); 顶部确保数据损坏
Dan Jay

1

您可以尝试这个吗,readfile需要完整的文件路径。

        $filename='/pdf/jobs/pdffile.pdf';            
        $url_download = BASE_URL . RELATIVE_PATH . $filename;            

        //header("Content-type:application/pdf");   
        header("Content-type: application/octet-stream");                       
        header("Content-Disposition:inline;filename='".basename($filename)."'");            
        header('Content-Length: ' . filesize($filename));
        header("Cache-control: private"); //use this to open files directly                     
        readfile($filename);

0

您需要定义文件的大小...

header('Content-Length: ' . filesize($file));

这行是错误的:

header(“ Content-Disposition:inline; filename ='$ filename”);

您搞砸了配额。


4
不,您不需要提供文件的大小。这也可能是错误的来源。
Marcel Korpel 2013年

取决于PDF插件版本。给予它是安全的。
Flash Thunder

无法使它正常工作。我要测试的$ file变量的大小是多少?它是文件URL ./pdf/jobs/pdftitle.pdf吗?
useyourillusiontoo

是的,它是文件位置...也许您在弄乱路径?尝试给出绝对路径。
Flash Thunder
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.