下载文件php总是损坏

时间:2012-06-28 12:08:16

标签: php download

我试图制作一个脚本来从我的localhost下载图像。仅适用于学校项目。

我通过url获取文件名(“$ _GET ['file']”)。然后我运行这个脚本。每次文件损坏,无法查看。我想下载图像,但是当我尝试word文档时它也被损坏了。这是我的代码:

<?php
//get file
$file = $_GET['file'];
//set path of file
$path = $_SERVER['DOCUMENT_ROOT']."/blackbox/mediafiles/"; 
$fullPath = $path.$file;
if ($fd = fopen ($fullPath, "r")) {
    $path_parts = pathinfo($fullPath);
        header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // fore a download
        header("Content-type: application/octet-stream");
        header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
    header("Cache-control: private"); // open files directly
    while(!feof($fd)) {
        $buffer = fread($fd, 2048);
        echo $buffer;
    }
fclose ($fd);
exit;
?>

有人知道出了什么问题吗?

提前致谢!!

4 个答案:

答案 0 :(得分:3)

尝试以二进制模式显式打开文件:

if ($fd = fopen ($fullPath, "rb")) {

正如fopen所述的文档所述:

  

Windows提供了一个文本模式转换标志('t')   在处理文件时透明地将\ n转换为\ r \ n。在   相比之下,您也可以使用'b'来强制二进制模式,而不是   翻译您的数据。要使用这些标志,请指定“b”或“t”   模式参数的最后一个字符。

     

默认转换模式取决于SAPI和PHP版本   您正在使用,因此我们鼓励您始终指定   出于便携性原因的适当标志。你应该使用't'模式   如果您正在使用纯文本文件,并使用\ n来分隔   您的行结尾在您的脚本中,但希望您的文件可读   与记事本等应用程序。你应该在所有其他人中使用'b'   例。

     

如果在处理二进制文件时没有指定'b'标志,那么   您的数据可能会遇到奇怪的问题,包括图像损坏   文件和\ r \ n字符的奇怪问题。

答案 1 :(得分:1)

您可以使用readfile代替手动阅读文件和输出。

此外,请注意,$ _GET ['file']可以包含'../'并打开任何文件,这是一个安全风险。使用basename功能(如果所有文件都在同一目录中)或限制访问mediafiles目录之外的文件

<?php
//get file
$file = $_GET['file'];
//set path of file
$path = $_SERVER['DOCUMENT_ROOT']."/blackbox/mediafiles/"; 
$fullPath = $path. basename($file);
if (is_readable($fullPath) {
    $path_parts = pathinfo($fullPath);
    header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // fore a download
    header("Content-type: application/octet-stream");
    header("Content-length: " . filesize($fullPath));
    header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
    header("Cache-control: private"); // open files directly
    readfile($fullPath);
}
exit;
?>

答案 2 :(得分:1)

要么某些东西从PHP中抛出错误,要么在文件中的开始标记之前有前导空格(<?php)。

做两件事:

  • 确保<的{​​{1}} 文件中的第一个字符。确保您的脚本中没有字节顺序标记。
  • 将这些行添加到脚本顶部:<?php

请注意,如果禁用错误修复了您的问题,则表示存在需要修复的错误,这不是问题的最终解决方案!

使用readfile()也比打开文件指针并循环它更短,更安全,更有效。

答案 3 :(得分:1)

起初它不是你的答案。但你应该真的看看PHP中的安全性。在您的脚本上,您可以通过GET参数和DOCUMENT_ROOT访问所有文件。

不要相信用户。

您应首先过滤变量,或在将变量传递给用户之前将其映射到已知的文件列表。

PHPSec