下载文件损坏。内容类型无效?

5

我想让用户下载一个PDF文件,下载代码如下...但是出现了一个奇怪的错误,即使文件正在下载,我也收到了一个说文件在服务器上已经损坏的错误...有人可以帮助我指出我犯了什么错误吗?

<php

$name = $_POST["name_first"];

    $mail = $_POST['email'];


    $number = $_POST['phone_number'];

            $email_message = "first name: {$name} email is {$mail} number is {$number} ";
            mail('fanaa@gmail.com', 'Form Response', $email_message);

                if ($mail == "" OR $name == "" OR $number == "")
                    {
                        echo "Enter valid details  ";

                    }
                    else
                    {
                        header('Content-type: application/pdf');
                        header('Content-Disposition: attachment; filename="tokina.pdf"');
                        readfile('docs/tokina.pdf');

                    }
?>

您可以对原始文件和下载的文件进行二进制比较,以查找问题所在。如果差异仅在前两个或后两个字节中,我可能能够提供帮助。 - Salman A
你在执行的脚本中是否有额外的输出,例如空格、echo或其他内容? - KingCrunch
如果您的PDF文件没有问题,也许您可以使用像http://swiftmailer.org/这样的邮件库。 - Joko Wandiro
1
@KingCrunch 是的,这段代码实际上是 if 语句的一部分...在你的提问后我已经编辑了我的问题,请查看一下。 - user707165
我怀疑是 <?php ?> 标签的闭合问题。如果你的脚本开头或结尾处在 <?php ?> 标记之外有空白字符,将导致输出并造成数据损坏。或者,这可能是一个内容长度问题:你是否尝试添加如下一行代码?header("Content-length: ".filesize("tokina.pdf")); - Paolo Stefan
@Paolo Stefan...你让我修改的标题也没有起作用。PHP封闭符之间没有间隙,我检查了两次 :) - user707165
8个回答

13

我用这段代码下载PDF:

header ("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header('Content-Type: application/octetstream');
    header("Content-Transfer-Encoding: Binary");
    header("Content-length: ".filesize($file));
    header("Content-disposition: attachment; filename=\"".basename($filename)."\"");
    readfile("$file");                
  }

这样做应该没问题,确保没有空格或回车字符(完全不要转义php是最好的解决方案)。

如果您发现仍然有问题,请使用记事本打开已损坏的文件(里面可能会有一个php错误警告)。

希望能对您有所帮助!


1
请问$file是什么意思?我没有理解那部分。 - user707165
$file 是文件路径,例如 ../myfiles/thisone/example.pdf,在您的情况下,您可以将 $file = 'docs/tokina.pdf'。 - Abe Petrillo
Abe,也许如果你写成 readfile($file); 的话会更清晰。 - Prof. Falken
"Content-Type: application/octetstream" 这个头部让我很困扰。谢谢。 - Adi
在这种情况下,用记事本打开PDF文件是一个好建议。谢谢,它对我很有帮助。 - Onur Kucukkece

3

移除头部并查看页面,您是否看到任何错误信息?如果PHP输出的不是实际的PDF源代码,那么该文件将显示为已损坏。


1
如果我删除第一行的标题...它会输出tokina.pdf.htm。 - user707165
1
如果我删除了两个头文件,PHP会显示一个带有二进制编码行的页面。 - user707165
很显然但是我没想到,这很有帮助,谢谢! - darma

1
header('Content-type: application/pdf');

启用 PHP 扩展 php_gettext,然后你就完成了。


0

你的PDF文件tokina.pdf可能没有上传或者不在与PHP文件相同的目录中。这就是为什么它保存为“tokina.pdf.htm”的原因——它加载了404页面的HTML。这就是为什么你的浏览器/PDF阅读器认为该文件已经“损坏”——因为它的扩展名是PDF,但其内容并非如此。

确保文件已上传,并且如果已上传,请确保readfile指向正确的路径。如果它不在同一个文件夹中,请使用相对/绝对路径,例如:

readfile('docs/tokina.pdf');

是的,内容类型应该是application/pdf


1
我正在使用WAMP服务器测试我的代码...PDF文件的位置在WAMP的“WWW”目录中。 - user707165

0

我使用

$download_path = your path (where to look for the files)
set_time_limit(0);
$file_url = $download_path . $data['link'];
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file_url). '"');
//then to read the file
readfile($file_url);

这通常对我有效


0

使用此脚本

   header('Content-Type: application/force-download');
   header('Content-Disposition: attachment; filename='.$filename);
   header('Content-Transfer-Encoding: binary');
   header('Content-Length: '.filesize($filenamepath));

   readfile($filenamepath);

我曾经遇到过同样的问题。通过使用 UltraEdit 等十六进制编辑器比较原始文件和下载文件,我发现损坏文件开头有一些字符。

问题在于,在 PHP 代码结束标记 ?> 后,我的代码中出现了多次行终止符。

删除 ?> 后面的所有行终止符,并阅读论坛文章 Downloaded Files are corrupt - Common Problem。这对我很有效。

希望这能帮到你。


0

尝试去掉双引号

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

所以它变成了

header('Content-type: application/octet-stream');

3
我认为PDF文件的内容类型应该是application/pdf。参见http://php.net/manual/en/function.header.php。 - boug
1
我最初尝试了application/pdf。经过一番研究后,我发现了关于application/octet-stream的信息,并将其集成到代码中。 - user707165

0

也许您的内容类型不正确。请尝试使用此类型:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接