PHP ZIP :: ExtractTo不提取任何文件

时间:2018-03-09 00:23:31

标签: php heroku ziparchive

在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轻松清除应用程序创建的文件。

虽然上面的代码有效,但我很想知道你是否看到了改进的机会。

1 个答案:

答案 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);
}

干杯。