【问题标题】:Script to download and extract zip files returns errors下载和解压 zip 文件的脚本返回错误
【发布时间】:2011-03-21 22:10:55
【问题描述】:

大家好,我编写了一个脚本,可以从远程源下载 zip 文件,然后应该将 zip 文件解压缩到一个目录中。下面是脚本:

    <?php
        $url = "http://example.com/some_file.zip";
        download($url,'file.zip');

        function download($url,$file_name = NULL){
          if($file_name == NULL){ $file_name = basename($url);}

          $url_stuff = parse_url($url);
          $port = isset($url_stuff['port']) ? $url_stuff['port'] : 80;

          $fp = fsockopen($url_stuff['host'], $port);
          if(!$fp){ return false;}

          $query  = 'GET ' . $url_stuff['path'] . " HTTP/1.0\n";
          $query .= 'Host: ' . $url_stuff['host'];
          $query .= "\n\n";

          fwrite($fp, $query);

          while ($tmp = fread($fp, 8192))   {
            $buffer .= $tmp;
          }

          preg_match('/Content-Length: ([0-9]+)/', $buffer, $parts);
          $file_binary = substr($buffer, - $parts[1]);
          if($file_name == NULL){
            $temp = explode(".",$url);
            $file_name = $temp[count($temp)-1];
          }
          if(!file_exists("packages")){ mkdir("packages", 0755);}
          $file_open = fopen("packages/" . $file_name,'w');
          if(!$file_open){ return false;}
          fwrite($file_open,$file_binary);

          $zip = zip_open(realpath("packages")."/".$file_name);
          if ($zip) {
            while ($zip_entry = zip_read($zip)) {
              $fp = fopen("some_dir/".zip_entry_name($zip_entry), "w");
              if(zip_entry_open($zip, $zip_entry, "r")) {
                $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
                fwrite($fp,"$buf");
                zip_entry_close($zip_entry);
                fclose($fp);
              }
            }
            zip_close($zip);
          }
          fclose($file_open);
          return true;
        }
   ?>

我遇到的问题是,虽然远程文件的下载工作完美无缺,但我似乎无法提取它。 zip_read()zip_close() 返回错误说它“期望参数 1 是资源,给定整数......”,我发现这意味着 zip_open() 无法提取并返回错误代码,这我发现它是“19”,意思是“Zip 文件功能错误:不是 zip 存档”。但是,我知道我正在下载的文件实际上是一个 zip 文件。谁能解释这种奇怪的行为并提供修复?将不胜感激!

【问题讨论】:

  • 您应该在进行压缩操作之前fclose($file_open)。此时您不再需要$file_open 句柄,并且在同一个文件中保留两个句柄很麻烦。不过,我认为这不是问题的原因。
  • 是的,这是有道理的,感谢您帮助清理。但是,是的,正如你所说,这个问题根本没有改变。
  • 顺便说一句,我非常感谢以这种方式深入研究 HTTP 的努力,但是您是否考虑过使用 file_get_contents("http://.../")curl_open 等?
  • zip 常量页面的注释中有一个错误代码列表:php.net/manual/en/zip.constants.php(我不知道它们是否正确,但它可能有用。)
  • @mvds 我还没有,但它可能是我需要去的地方。它现在和将来可能会省去一些麻烦。我以前从未做过任何获取/读取远程文件的工作,所以我边走边学。我会看看这两个选项。我以前听说过关于 curl 的好消息。 @George 感谢您的信息,看起来很棒!

标签: php zip archive


【解决方案1】:

引用 php.net:“zip_open() ... 返回资源句柄以供以后与 zip_read() 和 zip_close() 一起使用,或者如果文件名不存在或出现其他错误,则返回错误数。”

这意味着你不能像那样测试if ($zip)。试试

if ( is_resource($zip) ) {
    // stuff
} else {
    print "Zip_open() returned error $zip\n";
}

编辑:除此之外,您需要将响应正确地分成两部分。您严重依赖 Content-Length 参数。您不检查 preg_match 是否实际匹配。很多事情都可能出错,你应该检查这些事情。尝试在第一个空行上拆分内容(explode 上的 \r\n\r\n 或类似的东西)

除了fread() 循环应该检查feof(),因为如果由于某种原因你会遇到空读,你现在会停止阅读。从 php.net 复制粘贴:

while (!feof($handle)) {
    $contents .= fread($handle, 8192);
}

但我们可以在这里继续。主要有以下三点:

  • 阅读精彩的手册 (php.net)
  • 检查返回值
  • 不要假设你知道你不知道的事情

这些是相关的:您必须查阅手册以查看可能遇到的返回值。

【讨论】:

  • 谢谢,这是有道理的,我已经进行了更改,但是现在不是打印错误,而是跳过提取部分,因为 zip_open 仍然无法打开 zip 文件。所以这并没有解决问题。
  • @ben 然后弄清楚为什么它没有打开文件。例如,realpath("packages")."/".$file_name 是正确的路径吗?
  • 老实说,我认为这是我的代码中的某些内容,也许是下载不正确?这就是为什么我包括那个下载部分。我认为这是因为我在使用文件管理器打开文件时遇到问题,它说 zip 格式无效。但是我仍然可以用 7-zip 打开它,所以它必须是某种格式的东西。但是我知道它不是原始文件,因为如果我将它下载到我的计算机上并解压缩它就可以正常工作。例如,我还使用 wordpress zip 文件对其进行了测试,所以不是这样。
  • 你下载了这个脚本保存的文件了吗?如果是这样,zip_open 可能只是比一般的解压缩程序更挑剔,或者它是 php 的 zip_open 不支持的 zip 格式。
  • 是的,我想一定是这样的。它只是更挑剔/不支持 zip 格式。感谢您提供有关如何清理我的代码的帮助和建议。
猜你喜欢
  • 1970-01-01
  • 2021-03-07
  • 2016-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多