使用fopen(),fread(),feof()下载文件...下载的文件已损坏

时间:2011-11-05 23:55:47

标签: php

我有一个从服务器下载文件的脚本,一切都很好用。但是当下载文件时,它是jpg或png文件。我似乎无法用任何程序打开它来查看它。 (Windows照片库或烟花)

当我下载视频文件(avi)时。我无法用Windows媒体播放器打开它,但我可以用vlc媒体播放器打开它。

我总是收到错误消息,无法读取文件或文件损坏。

这是代码,它是可靠的还是我应该考虑使用fsocketopen或curl。

我尝试改变标题,在网上寻找更多答案,但没有运气。

任何人都知道什么是错的?

chmod("extensions_img/test.jpg",0755);

$fullPath = "http://www.website_url.com/extensions_img/test.jpg";

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

    $fsize = filesize("extensions_img/test.jpg");

    $path_parts = pathinfo($fullPath);
    $ext = strtolower($path_parts["extension"]);

    switch($ext) {

        case "pdf":
            $ctype = "application/pdf";
            break;
        case "exe":
            $ctype = "application/octet-stream";
            break;
        case "zip":
            $ctype = "application/zip";
            break;
        case "doc":
            $ctype = "application/msword";
            break;
        case "xls":
            $ctype = "application/vnd.ms-excel";
            break;
        case "ppt":
            $ctype = "application/vnd.ms-powerpoint";
            break;
        case "gif":
            $ctype = "image/gif";
            break;
        case "png":
            $ctype = "image/png";
            break;
        case "jpeg":
            $ctype = "image/jpg";
            break;
        case "jpg":
            $ctype = "image/jpg";
            break;
        case "mp3":
            $ctype = "audio/mp3";
            break;
        case "wav":
            $ctype = "audio/x-wav";
            break;
        case "wma":
            $ctype = "audio/x-wav";
            break;
        case "mpeg":
            $ctype = "video/mpeg";
            break;
        case "mpg":
            $ctype = "video/mpeg";
            break;
        case "mpe":
            $ctype = "video/mpeg";
            break;
        case "mov":
            $ctype = "video/quicktime";
            break;
        case "avi":
            $ctype = "video/x-msvideo";
            break;
        case "src":
            $ctype = "plain/text";
            break;
        default:
            $ctype = "application/force-download";
    }

    header("Pragma: public");

    header("Expires: 0");

    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

    header("Cache-Control: private",false);

    header("Content-type: " . $ctype);

    header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");

    header("Content-Transfer-Encoding: binary");

    header("Content-length: $fsize");
    header("Cache-control: public"); //use this to open files directly

    while(!feof($fd)) {
        $buffer = fread($fd, 4096);
    flush();
    }
}
fclose ($fd);

3 个答案:

答案 0 :(得分:1)

尝试:

while(!feof($fd)) {
    echo fread($fd, 4096);
    flush();
}

你没有回应任何东西,所以你的文件可能是空的?

答案 1 :(得分:0)

您正在发送包含您错误获取的文件大小的Content-length:标题。

// You are opening a remote file:
$fullPath = "http://www.website_url.com/extensions_img/test.jpg";

// You are retrieving the filesize of a local file that may or may not exist
$fsize = filesize("extensions_img/test.jpg");

所以,最有可能的是,您的Content-length看起来如下:

 header("Content-length: 0");

...除非您有一个同名的实际本地文件,否则您将提供其文件大小而不是预期的远程文件。

根据filesize() documentation,支持一些URL包装器。您可能会尝试从远程文件中检索文件大小:

  

从PHP 5.0.0开始,此函数也可以与某些URL包装器一起使用。请参阅支持的协议和包装以确定
  哪个包装器支持stat()系列功能。

$fsize = filesize($fullpath);

答案 2 :(得分:0)

使用filesize($url)将下载文件两次。当有file_get_contentsfopen/fread时,不知道你为什么要使用fpassthru

$data = file_get_contents($url);
$size = strlen($data);
$mime = current(preg_grep('/^Content-Type:/i', $http_response_header));

请注意这也是如何为您提供正确的MIME类型(为简单起见,只需通过header传递整个动态)。甚至是所有标题。