web-dev-qa-db-ja.com

ZipArchive Closeに関する警告

一部の画像のauto-Zipスクリプトの問題を修正しようとしています。これは少し前に書いたもので、現在まで機能していました。すべてが$Zip->close();まで問題ないようで、次のようになります。

_ <b>Warning</b>:  ZipArchive::close(): Read error: No such file or directory in <b></b> on line <b>287</b><br />
_

私はドキュメントといくつかのフォーラムを読み、これが次のシナリオのいずれかで発生する可能性があることを発見しました:

  1. PHP 5.6であるため、Zipに実際のファイルが追加されていない場合は、最近PHP 5.6。 ____。]
    • 追加する前に各ファイルが存在することを確認します
    • 空ではないダミーのテキストファイルをZipに追加しようとしました。ファイルのfile_exists()と同様に、それをZipに追加するとtrueが返されます
    • _$Zip->numFiles_をエコーし​​、少なくとも1の数を与える場合(Zipにダミー以外のファイルがない場合)
  2. Zipを書き込む必要があるディレクトリが存在しないか、適切な権限がない場合:これは事実ではないようですが、念のため、テキストファイルを同じフォルダーに書き込みました同じスクリプトで問題はありませんでした
  3. 一時ディレクトリへの書き込みに問題がある場合。これを確認するのは少し難しいですが、同じシステムに機能するアップロードスクリプトがあり、ディスク領域の問題などがないことを確認しました。

これが関連するコードです。一部の変数は事前に定義されています。すべての問題をログに書き込みますが、このスクリプトはエントリを生成しません。

_$Zip_file = 'Project'.$project_id.'.Zip';
$Zip = new ZipArchive;
if ($Zip_result = $Zip->open($Zip_path.'/'.$Zip_file, ZIPARCHIVE::CREATE) !== true) {
    echo 'Error creating Zip for project: '.$project_id.'. Error code: '.$Zip_result;
    help::debugLog('Error creating Zip for project: '.$project_id.'. Error code: '.$Zip_result);
    return false;
}
$file_list = array();

foreach ($item_thumbs as $item)
{
    $full_thumb_path = $thumb_dir.'/'.$item['thumb'];
    if (file_exists($full_thumb_path) and $item['thumb'])
    {
        $file_added = $Zip->addFile($full_thumb_path, basename($item['thumb']));
        if (!$file_added)
            help::debugLog('Failed to add item thumb to project Zip. Project: '.$project_id.', file name: '.$item['thumb']);
        else
            $file_list[] = $item['thumb'];
    }
    elseif ($item['thumb']) /* If thumb indicated in DB doesn't exist in file system */
        help::debugLog('Item thumb file '.$item['thumb'].' from item: '.$item['id'].' is missing from its indended location: '.$full_thumb_path);
}

/* Added 2016-05-18 -- creates dummy file for the Zip listing its contents, important in case Zip is empty */
$file_list_path = $Zip_path.'/file_list.txt';
if (!($file_list_file = fopen($file_list_path, 'w+')))
    help::debugLog('Failed to create list file (intended for Zip) for project: '.$project_id);
fwrite($file_list_file, "File list:\n");
fwrite($file_list_file, implode("\n", $file_list));
if (file_exists($file_list_path))
{
    fclose($file_list_file);
    if (!$Zip->addFile($file_list_path))
        help::debugLog('Failed to add list file to project Zip for project: '.$project_id);
    unlink($file_list_path);
}
else
    help::debugLog('Failed to create list file (intended for Zip) for project: '.$project_id);

$Zip->close(); // line 287
_
13
Ynhockey

解決策は非常に単純であることがわかりました、そしてそれは実際にドキュメント(php.net)のコメントの1つで参照されています:

一部の人には少し明白に思えるかもしれませんが、それは私の代理としての見落としでした。

削除するファイルをZipファイルに追加する場合は、close()関数を呼び出した後で必ず削除してください。

オブジェクトに追加されたファイルが保存時に使用できない場合、Zipファイルは作成されません。

(ソース: https://www.php.net/manual/en/ziparchive.close.php#93322

したがって、上記のコードから、「ダミー」テキストファイルはZipが閉じられる前に削除され、必然的にZipの作成時にファイルが存在しなくなります。

Zipが一時的な場所に作成され、close()の最終的な場所にのみ移動したと私は信じる十分な理由がありました。これはそうではないことがわかりました。

13
Ynhockey