4

ダウンロードスクリプトに非常に奇妙な問題があります

それは基本的に

1.「GET」メソッドでファイルIDを取得します

2.データベースからそのファイルの名前と場所を取得します

3.ヘッダーと読み取りファイルを使用してクライアントに送信します

しかし不思議なことに、そのファイルは常に破損または破損しているとして出てきます

zipまたはrarファイルの場合のようにファイルサイズは適切で、正常に開きます

しかし、その中の圧縮ファイルを開くことができません、そしてそれは私がファイル破損エラーを受け取るときです

コードに問題があった場合、これは奇妙なことです。zipファイルを開くことさえできないはずです(または少なくとも私はそうすべきではないと思います)

もう1つは、ヘッダーを送信する直前に、すべてが正常であることを確認するために、そのパスを含むファイルを印刷したことです。

私はファイルアドレスを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;

私はヘッダーを数回チェックしましたが、それらは問題ありません(私は思います)、念のために人に知られているすべてのヘッダーも追加しました!

おそらくそれは文字エンコードやフォルダ権限のようなスクリプト以外のものだと思い始めています!またはそのようなもの!!

私は何かが足りないのですか?

4

5 に答える 5

7

これは、強制的にダウンロードするためのコードの割り当てのようです。これは、私がいつも使用している素晴らしい関数です。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);
}
?>
于 2012-04-13T17:12:24.730 に答える
4
    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);


}
于 2015-10-26T12:30:47.210 に答える
3

とても素敵で、役に立ちました...

しかし、コードに問題があります-

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

次のように変更してください-

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

あなたはそれを閉じるのを忘れています。

于 2012-12-08T21:22:17.103 に答える
2

スクリプトにNOTICEまたはWARNINGが含まれている可能性があります。スクリプトに加えて、エラーレポートを無効にしてみてください。

error_reporting(0);
于 2012-04-13T17:16:06.293 に答える
0

最後の行の後にコードが実行されていないことを確認してくださいreadfile(FILE_NAME)

MVCフレームワークはその後もビューをレンダリングし続けるため、die();または最後の行として追加する必要がありましたexit();readfile

于 2017-09-27T10:56:11.593 に答える