【问题标题】:Why is my downloaded file is always damaged or corrupted?为什么我下载的文件总是损坏或损坏?
【发布时间】:2012-04-13 16:55:52
【问题描述】:

我的下载脚本有一个非常奇怪的问题

基本上

1.使用“GET”方法获取文件id

2.从数据库中获取该文件的名称和位置

3.将其与标头和读取文件一起发送给客户端

但奇怪的是,该文件总是以损坏或损坏的形式出现

喜欢它是 zip 还是 rar 文件 文件大小合适,可以正常打开

但我无法打开其中的压缩文件,这就是我收到文件损坏错误的时候

这很奇怪,因为如果代码有问题,我什至不能打开 zip 文件(或者至少我认为我不应该)

另一件事是我在发送标头之前已打印出文件及其路径,以确保一切正常

我已经把文件地址放在url上并下载了文件,文件没问题

所以在发送标头之前一切都很好

这是我的代码

        $file_id = isset($_GET['id']) && (int)$_GET['id'] != 0 ? (int)$_GET['id'] : exit;
        
        
        //////// finging file info
        $file = comon::get_all_by_condition('files' , 'id' , $file_id );
        if(!$file) exit;
        foreach($file as $file){
        $location = $file['location'];
        $filename = $file['file_name'];
        }
        /////////////


        $site = comon::get_site_domian();
        
        $ext = trim(end(explode('.' , $filename )));
        $abslout_path = 'http://'.$site.'/'.$location.'/'.$filename;
        $relative = $location.'/'.$filename;
        

    
    ////////////////// content type 
            switch($ext) {
            case 'txt':
                $cType = 'text/plain'; 
            break;              
            case 'pdf':
                $cType = 'application/pdf'; 
            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':
            case 'jpg':
                $cType = 'image/jpg';
            break;
    
            default:
                $cType = 'application/force-download';
            break;
        }
   //////////////// just checking 

   if(!file_exists($relative)){
        echo $relative;
        echo '<br />';
        exit;
        }
    
    if( !is_readable( $relative ) )
    exit('its not redable');
    


    if( headers_sent() )
    exit('headers ? already sent !! ');
        

    
    header( 'Pragma: public' ); 
    header( 'Expires: 0' );
    header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
    header( 'Cache-Control: private', false ); // required for certain browsers 
    header( 'Content-Description:File Transfer' );
    header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
    header( 'Content-Type:'.$cType);
    header( 'Content-Disposition: attachment; filename="'. basename($filename) . '";' );
    header( 'Content-Transfer-Encoding: binary' );
    header( 'Content-Length: ' . filesize($relative) );
    readfile($abslout_path);
    exit;

我已经检查了几次标题,它们很好(我认为),我还添加了人类已知的每个标题以确保!

我开始想也许这不是脚本 像字符编码或文件夹权限!或类似的东西!!

我错过了什么吗?

【问题讨论】:

    标签: php file download


    【解决方案1】:

    这似乎是为了强制下载而分配的代码,这是我一直使用的一个不错的功能。它也可以处理超过 2GB 的文件。

    <?php 
    $file_id = (isset($_GET['id']) && (int)$_GET['id'] != 0) ? (int)$_GET['id'] : exit;
    
    /*finding file info*/
    $file = comon::get_all_by_condition('files', 'id', $file_id);
    $path = $file['location'] . '/' . $file['file_name'];
    
    if (!is_file($path)) {
        echo 'File not found.('.$path.')';
    } elseif (is_dir($path)) {
        echo 'Cannot download folder.';
    } else {
        send_download($path);
    }
    
    return;
    
    //The function with example headers
    function send_download($file) {
        $basename = basename($file);
        $length   = sprintf("%u", filesize($file));
    
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . $basename . '"');
        header('Content-Transfer-Encoding: binary');
        header('Connection: Keep-Alive');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . $length);
    
        set_time_limit(0);
        readfile($file);
    }
    ?>
    

    【讨论】:

    • @DanBray 多么糟糕的编辑,对社区的批准感到羞耻
    • @LawrenceCherone 让代码工作有什么可怕的?该代码缺少)。你认为留下有错别字的代码更好吗?失踪的) 可能会使人们感到困惑并浪费他们大量的时间。
    • (is_dir($path)) 上的好地方,但其余的编辑只是个人语法偏好。
    • @LawrenceCherone 它不会让我只添加缺少的),因为我必须编辑最少数量的字符。我想我可以在底部输入一个简短的短语。
    【解决方案2】:
        if (file_exists($file)) {
    set_time_limit(0);
            header('Connection: Keep-Alive');
        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);
    
    
    }
    

    【讨论】:

    • 这对我来说是完美的。下载的文件没有损坏。我使用 Lawrence Cherone 建议的 php 脚本,但下载的文件仍然损坏。感谢 Altair CA。谢谢大家。
    【解决方案3】:

    很好,也很有帮助...

    但是你的代码有问题-

    header('Content-Disposition: attachment;
    filename="'.basename($file).'"';
    

    请使用以下内容进行更改 -

    header('Content-Disposition: attachment;
    filename="'.basename($file).'"');
    

    你忘记关闭它了。

    【讨论】:

      【解决方案4】:

      您的脚本可能包含 NOTICE 或 WARNING,请尝试在您的脚本之上禁用错误报告:

      error_reporting(0);
      

      【讨论】:

        【解决方案5】:

        确保在最后一行readfile(FILE_NAME)之后没有执行任何代码

        我不得不在最后一行添加die();exit();,因为MVC 框架在readfile 之后继续渲染视图

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-24
          • 1970-01-01
          • 2023-04-10
          • 1970-01-01
          • 2015-07-14
          • 2015-07-16
          • 2017-12-04
          • 2019-01-28
          相关资源
          最近更新 更多