1

ハイヒ、

zip ファイルのダウンロードを求める前に、ユーザーが必要なパンフレットを選択できる複数のチェック ボックスを備えたフォームがあります。zipアーカイブのダウンロード機能は問題なく動作しています。しかし、ファイル全体 (たとえば 8MB) をダウンロードせずにダウンロード セッションが終了し、ダウンロードした zip ファイルが破損していることがわかりました。

以下のコードを参照しても、問題は解決しません。調べる必要がある設定は何か、または機能を見逃しているのか、誰でもアドバイスできますか?

if($send) {     
    // Make sure program execution doesn't time out
    // Set maximum script execution time in seconds (0 means no limit)
    set_time_limit(0);

    $post = $_POST;     
    $file_folder = "pdf/";  // folder to load files
    $zip = new ZipArchive();    // Load zip library 
    $zip_name = "File-".time().".zip";          // Zip name
    if($zip->open($zip_name, ZIPARCHIVE::CREATE)!==TRUE){       // Opening zip file to load files
        $error .=  "* Sorry ZIP creation failed at this time<br/>";
    }
    foreach($post['brochure'] as $file){                
        $zip->addFile($file_folder.$file);          // Adding files into zip
    }
    $zip->close();
    if(file_exists($zip_name)){
        // set headers push to download the zip
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: public");
        header('Content-type: application/zip');
        header("Content-Transfer-Encoding: Binary");
        header('Content-Disposition: attachment; filename="'.$zip_name.'"');
        header("Content-Length: ".filesize($zip_name)); 
        readfile($zip_name);
        // remove zip file is exists in temp path
        unlink($zip_name);

        $fp = @fopen($zip_name, "rb");
        if ($fp) {
         while(!feof($fp)) {
             print(fread($fp, 1024*8));
             flush(); // this is essential for large downloads
             if (connection_status()!=0) {
                 @fclose($file);
                 die();
             }
         }
         @fclose($file);
        }
    }
4

3 に答える 3

1

「readfile()」を作成する代わりに、この種の解決策を試しましたか?

if(file_exists($zip_name)){
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header('Content-type: application/zip');
    header("Content-Transfer-Encoding: Binary");
    header('Content-Disposition: attachment; filename="'.$zip_name.'"');
    header("Content-Length: ".filesize($zip_name)); 

    echo file_get_contents($file);
    exit
}

私にとっては簡単で、何度もうまくいきました。

この後、私が見る問題は、あなたが作ることです:

unlink($zip_name);
$fp = @fopen($zip_name, "rb");
if ($fp) {
    ...
}

ファイルを開く前にリンクを解除するため、コードのこの部分は実行しないでください。

于 2012-07-18T07:58:04.740 に答える
0

まず第一に、あなたは直前にif ($fp) {...}実行したので、あなたのブロックは決して実行されるべきではありません。unlink($zip_name);したがって、このブロックは役に立ちません。

二次的に、私はあなたが置き換えることをお勧めします

readfile($zip_name);

ob_clean();
flush();
readfile($zip_name);

これにより、予期しない境界線の影響を防ぐことができます。

そして最後に、まだ破損したアーカイブがある場合(私は信じています)、ダウンロードのフラッシュの前、最中、または後に何らかのPHPエラーが発生したためだと思います(PHPコードは後に終了していないようですので注意してください)ダウンロードするため、コードが続行され、後にエラーが発生する可能性があります)。このようなPHPエラーまたはPHP通知が発生した場合は、PHPエラーメッセージがストリーミングとともに出力されています。これは簡単に確認できます。破損したアーカイブをテキストエディタで開いてバイナリの内容を確認すると、アーカイブのバイナリの内容の最初または一番下にPHPエラーメッセージが明確に表示され、読みやすくなります。HEXAモードでアーカイブを開く必要はありません。

于 2012-07-18T08:10:45.513 に答える
0

以下のコードで私の問題を解決することができます。基本的に、fopenを呼び出す前にファイルのリンクを解除するべきではありません。

if($send) {
    // Make sure program execution doesn't time out
    // Set maximum script execution time in seconds (0 means no limit)
    set_time_limit(0);

    $post = $_POST;     
    $file_folder = "pdf/";  // folder to load files
    $zip = new ZipArchive();    // Load zip library 
    $zip_name = "File-".time().".zip";          // Zip name
    if($zip->open($zip_name, ZIPARCHIVE::CREATE)!==TRUE){       // Opening zip file to load files
        $error .=  "* Sorry ZIP creation failed at this time<br/>";
    }
    foreach($post['brochure'] as $file){                
        $zip->addFile($file_folder.$file);          // Adding files into zip
    }
    $zip->close();
    if(file_exists($zip_name)){

        // set headers push to download the zip
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Cache-Control: public");
        header('Content-type: application/zip');
        header("Content-Transfer-Encoding: Binary");
        header('Content-Disposition: attachment; filename="'.$zip_name.'"');
        header("Content-Length: ".filesize($zip_name)); 

        //readfile($zip_name);
        // remove zip file is exists in temp path
        //unlink($zip_name);

        $fp = @fopen($zip_name, "rb");
        if ($fp) {
         while(!feof($fp)) {
             echo fread($fp, 8192);
             flush(); // this is essential for large downloads
             if (connection_status()!=0) {
                 @fclose($zip_name);
                 die();
             }
         }
         @fclose($zip_name);
        }
        unlink($zip_name);
    }
}
于 2012-07-19T03:42:38.203 に答える