在PHP中使用ZipArchive类时,我遇到了意外行为。我希望代码块能够获取Zip文件并将其所有内容提取到目录中。我在http://php.net/manual/en/ziparchive.open.php上遵循了文档(示例#1的组合和webdeveric dot com的用户注释中的eric)。但我能做的最好的事情就是创建目录。没有档案! Zip存档不是空的,所以我不确定为什么我会得到这种行为。它发生在我的本地和生产环境中。
以下是代码:
function getZip ($unitID, $zipLink) {
// First, check to see if the LMS Asset exists in the ephemeral file system before grabbing the file from file storage
$assetPath = "assets/".$unitID."/";
if (file_exists($assetPath)) {
return;
} else {
$zip = new ZipArchive;
if ($zip->open($zipLink, 0|1)===TRUE) {
$zip->extractTo($assetPath);
$zip->close();
} else {
echo "Unable to open file because of an error: ";
echo $zip->open($zipLink);
}
}
}
如果链接指向远程资源,似乎zip-> open()不喜欢它。如果我指向已经存在于文件系统上的Zip文件,我能够使它工作。由于这不是用例所需的,我必须弄清楚如何首先从远程位置获取文件,将其保存为本地文件系统中的临时文件,然后执行命令。这是我最终得到的代码:
function getZip ($unitID, $zipLink) {
// Before doing anything, check to see if the file exists.
$assetPath = "assets/".$unitID."/index.html";
if (file_exists($assetPath)) {
echo "The file already exists!";
return;
} else {
$path = "assets/".$unitID;
$zipFileRemote = file_get_contents($zipLink);
$zipFileLocal = "mytempzip".$unitID.".zip";
file_put_contents($zipFileLocal, $zipFileRemote);
echo "<br/>".$path;
echo $zipLink;
$zip = new ZipArchive;
$res = $zip->open($zipFileLocal);
if ($res===TRUE) {
$zip->extractTo($path);
$zip->close();
unlink($zipFileLocal);
} else {
echo "There was an error: ".$res;
}
}
}
我还更新了条件以检查解压缩文件位置中的index.html文件。如果zip文件的内容已存在于文件系统中,我不希望该函数执行任何操作。如果远程zip文件的内容发生变化,我可以看到这是一个问题,但由于这个应用程序存在于Heroku上,并且它使用了一个短暂的文件系统,我可以通过重新启动dyno轻松清除应用程序创建的文件。
虽然上面的代码有效,但我很想知道你是否看到了改进的机会。
答案 0 :(得分:0)
我相信这一行是你的问题。
$assetPath = "assets/".$unitID."/";
if (file_exists($assetPath)) {
return;
}else{
//....
}
应为if(!file_exists($assetPath))
,或英文If not file or dir exists, do this
,使用&#34; Bang(!)&#34;
函数file_exists
检查文件和目录,因此您要说明目录是否存在return
。因此,它永远不会运行else
块中的内容,也永远不会提取文件。但这并不意外,它完全按照你的要求去做。
http://php.net/manual/en/function.file-exists.php
file_exists - 检查文件或目录是否存在
在任何情况下,我都不建议做一个返回,最好抛出一个异常,否则输出一些东西。比这更清楚了。所以像这样:
if (!file_exists($assetPath)) {
throw new Exception("Directory ".dirname($assetPath)." does not exist");
}else{
这只是一个简单的&#34;逻辑&#34;错误,没什么大不了的。
最后一件事是个人我会使用is_dir
而不是file_exists
。我会说如果你不小心传入文件名,这实际上可以避免一些问题。但是因为你在它之后添加/
,这可能不会发生。所以我们可以把它放到&#34; Readability&#34;
<强>更新强> 要检查文件夹是否为空,这实在是你想要的(我还添加了mkdir来创建文件夹,但这是可选的)
$assetPath = "assets/".$unitID."/"
if(is_dir($assetPath)){
$contents = array_diff(scandir($assetPath), ['.','..']); //remove . and ..
if(empty($contents)) return;
}else{
mkdir($assetPath, 0755, true); //recursive [optional]
}
//obviously if it returned we wouldn't be here...
$zip = new ZipArchive;
if ($zip->open($zipLink, 0|1)===TRUE) {
$zip->extractTo($assetPath);
$zip->close();
} else {
echo "Unable to open file because of an error: ";
echo $zip->open($zipLink);
}
干杯。