9

我的用户通过 FTP 上传 zip 文件,然后一个 php 文件将它们添加到 RSS 文件中。

我正在尝试找到一种方法来检查每个 ZIP 文件以验证文件并检查它是否损坏或上传是否未完成。有没有办法做到这一点 ?

4

3 回答 3

15

的结果open也可以是true应首先对其进行评估。如果没有 check ZipArchive:ER_NOZIP,它等于 (int) 1,将始终匹配。

$zip = new ZipArchive();
$res = $zip->open('test.zip', ZipArchive::CHECKCONS);
if ($res !== TRUE) {
    switch($res) {
        case ZipArchive::ER_NOZIP:
            die('not a zip archive');
        case ZipArchive::ER_INCONS :
            die('consistency check failed');
        case ZipArchive::ER_CRC :
            die('checksum failed');
        default:
            die('error ' . $res);
    }
}
于 2016-01-18T21:35:31.533 回答
2

你可以使用这个ZipArchive类。自 PHP5.2 以来,它是标准 php 发行版的一部分。

像这样使用它:

$zip = new ZipArchive();

// ZipArchive::CHECKCONS will enforce additional consistency checks
$res = $zip->open('test.zip', ZipArchive::CHECKCONS);
if(!$res) {
    throw Exception('Error opening zip');
}

switch($res) {

    case ZipArchive::ER_NOZIP :
        die('not a zip archive');
    case ZipArchive::ER_INCONS :
        die('consistency check failed');
    case ZipArchive::ER_CRC :
        die('checksum failed');
    
    // ... check for the other types of errors listed in the manual
}

如果 zip 存档不完整或以其他方式损坏$zip->open()将返回ZipArchive::ER_NOZIP

于 2013-07-06T03:48:34.623 回答
1

如何检测 CRC 不匹配的损坏文件:

ZipArchive 似乎无法检测到损坏的文件。ZipArchive::CHECKCONS 没有帮助,只有当它根本不是 ZIP 文件时。它在我的测试中愉快地解压了损坏的文件,并且没有通知下载数据的客户端。

为测试创建损坏的存档很简单 - 压缩一些文件并在生成的 ZIP 文件中使用十六进制编辑器更改一个字节。现在,您可以使用 ZIP 应用程序测试该文件,以了解存档中的哪个文件已损坏。

您可以简单地在服务器上验证较小文件的 CRC:

<?php
$maxsize = 1024*1024;
$z = new ZipArchive;
$r = $z->open("foo.zip", ZipArchive::CHECKCONS);
if($r !== TRUE)
  die('ZIP error when trying to open "foo.zip": '.$r);

$stat = $z->statName("mybrokenfile.txt");
if($stat['size'] > $maxsize)
  die('File too large, decompression denied');
$s = $z->getStream($file);
$data = stream_get_contents($s, $maxsize);
fclose($s);
if($stat['crc'] != crc32($data))
  die('File is corrupt!');
//echo 'File is valid';

//you may send the file to the client now if you didn't output anything before
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="mybrokenfile.txt"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . $stat['size']);
ob_clean();
echo $data;
$z->close();
?>

如果文件在服务器上不能完全解压缩,但由于文件大小而在流式传输到客户端时解压缩,则文件传输已经开始并且稍后打印错误消息将不起作用。也许最好的方法是在关闭文件传输之前中断连接。客户端应该能够将其检测为损坏的下载。在服务器端需要一个函数,它可以逐步计算流数据的 CRC32。

于 2016-08-17T06:34:52.350 回答