我有以下代码,它从外部源下载一个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 文件下载因任何原因延迟或缓慢,它可能会崩溃,为什么要尝试解压缩不存在的文件。
如果这是有道理的。
file_put_contents可以根据主机的不同而以不同的方式工作,但据我所知,它的格式不会像人们应该期望的那样锁定并发线程(除非严格指定)。同样值得记住的是,PHP在Windows上的行为与在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 {
//
}
这将防止您调用此页面两次并且两个页面都尝试访问同一文件的情况。这是可能发生的情况:第 1 页下载 zip。第 1 页开始提取 zip。第 2 页下载 zip 替换旧文件第 1 页会像:我的 zip 怎么了?O.O
试试这样的事情
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;
}