PHP下载并解压缩zip文件

6
我有以下代码,可以从外部源下载zip文件并解压缩:
file_put_contents("my-zip.zip", fopen("http://www.externalsite.com/zipfile.zip", 'r'));

$zip = new ZipArchive;
$res = $zip->open('my-zip.zip');
if ($res === TRUE) {
  $zip->extractTo('/extract-here');
  $zip->close();
  //
} else {
  //
}

这个代码目前运行良好,但我的问题是,解压文件的过程是否会等到 file_put_contents 函数完成后再进行?还是会在中途尝试运行?

目前看起来一切都很正常,但我在想如果zip文件下载延迟或者出现了其他原因导致速度减慢,那么尝试解压不存在的文件可能会导致程序崩溃。

如果这样说没问题的话。


1
每个 PHP 脚本中的指令都会执行直到完成,然后才会继续执行下一条指令。 - Mark Baker
谢谢你,马克! - Lee
2个回答

8

file_put_contents函数在不同的主机上可能有所不同,但据我所知,它的格式不会像人们期望的那样锁定并发线程(除非严格指定)。此外,需要记住PHP在Windows和Linux上的行为不同(而许多人,不是在Linux服务器上开发,就是在Windows上开发后再部署到Linux服务器上)。

你可以尝试像这样做以确保文件已成功下载。(同时没有并发线程);

$file = fopen("my-zip.zip", "w+");
if (flock($file, LOCK_EX)) {
    fwrite($file, fopen("http://www.externalsite.com/zipfile.zip", 'r'));
    $zip = new ZipArchive;
    $res = $zip->open('my-zip.zip');
    if ($res === TRUE) {
      $zip->extractTo('/extract-here');
      $zip->close();
      //
    } else {
      //
    }
    flock($file, LOCK_UN);
} else {
    // die("Couldn't download the zip file.");
}
fclose($file);

这可能也起作用。
$f = file_put_contents("my-zip.zip", fopen("http://www.externalsite.com/zipfile.zip", 'r'), LOCK_EX);
if(FALSE === $f)
    die("Couldn't write to file.");
$zip = new ZipArchive;
$res = $zip->open('my-zip.zip');
if ($res === TRUE) {
  $zip->extractTo('/extract-here');
  $zip->close();
  //
} else {
  //
}

如果您调用该页面两次且两个页面都试图访问同一文件,则会发生以下情况:这将防止: 第一页下载zip。 第一页开始提取zip。 第二页下载zip并替换旧的zip。 第一页可能会出现:我的zip去哪了?O.O


您也可以(大多数情况下,如果不是全部的话)通过使用临时名称来消除并发问题。因此,使用file_put_contents(tempnam(sys_get_temp_dir(),''),$url)将$ url中的zip文件下载到系统临时目录中的临时文件中。这也意味着,如果您在Windez上开发并部署到*nix,则不需要在环境之间更改代码。 - Aaron Mason
1
@Felype 代码运行得很好,但是在成功解压缩后,我如何返回文件/数据呢?Zip文件中的文件是一个.xml文件,我需要将其输出。 - Richard Mišenčík
您可以使用基本的“将文件作为下载发送”的代码,例如 header("Content-Type: application/xml"); header("Content-Length:".filesize($filePath)); header("Content-Disposition: attachment; filename=".$filename); readfile($filePath); - Felype

2
最初的回答:尝试像这样做:

尝试这样做:

function downloadUnzipGetContents($url) {
    $data = file_get_contents($url);

    $path = tempnam(sys_get_temp_dir(), 'prefix');

    $temp = fopen($path, 'w');
    fwrite($temp, $data);
    fseek($temp, 0);
    fclose($temp);

    $pathExtracted = tempnam(sys_get_temp_dir(), 'prefix');

    $filenameInsideZip = 'test.csv';
    copy("zip://".$path."#".$filenameInsideZip, $pathExtracted);

    $data = file_get_contents($pathExtracted);

    unlink($path);
    unlink($pathExtracted);

    return $data;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接