2013-03-10 70 views
3

我有一個包含一個文件夾中的zip文件,包含多個文件夾和文件,像這樣從文件夾中的文件:PHP - 提取一個zip

myfile.zip
-firstlevel
--folder1
- -folder2
--folder3
--file1
--file2

現在,我想提取使用PHP的ZipArchive這個文件,但沒有「firstlevel 「文件夾。目前,結果是這樣的:

目的地/ firstlevel /文件夾1
目的地/ firstlevel /文件夾2
...

我想有是這樣的結果是:

目的地/文件夾1
目的地/文件夾2
...

我已經試過extractTo,其生產的第一提及結果和複製(),如建議here,但這似乎不工作。

我當前的代碼是在這裏:

if($zip->open('myfile.zip') === true) { 
     $firstlevel = $zip->getNameIndex(0); 
     for($i = 0; $i < $zip->numFiles; $i++) { 
       $entry = $zip->getNameIndex($i); 
       $pos = strpos($entry, $firstlevel); 
       if ($pos !== false) { 
         $file = substr($entry, strlen($firstlevel)); 
         if(strlen($file) > 0){ 
           $files[] = $file; 
         } 
       } 
     } 
     //attempt 1 (extractTo): 
     //$zip->extractTo('./test', $files); 

     //attempt 2 (copy): 
     foreach($files as $filename){ 
       copy('zip://'.$firstlevel.'/'.$filename, 'test/'.$filename); 
     } 
} 

我如何能實現我的目標,結果呢?

+0

現在情況如何?這些文件是否始終與頂層文件夾一起出現,或者文件是否以不同的方式出現?你怎麼知道頂層將永遠是空的? – 2013-03-10 16:50:20

+0

準確地說:這些文件總是帶有頂層文件夾,在服務器上解壓縮文件時我不需要它們。 – Harmageddon 2013-03-10 20:11:37

回答

0

看看我的Quick Unzipper腳本。上傳大型zip文件到服務器時,我寫了這個供個人使用。這是一個備份,並且1000個文件永遠使用FTP,因此使用zip文件更快。我使用Git和一切,但對我來說沒有別的選擇。我把這個php文件放在我想要文件去的目錄中,並把zip文件放在同一個目錄下。對於我的腳本,他們都必須在同一個目錄下操作。因爲我需要的東西都在同一個目錄中,所以這是一種簡單的方法來保護它以滿足我的需求。

快速Unzipper:https://github.com/incomepitbull/QuickUnzipper/blob/master/unzip.php

我鏈接的文件,因爲我不是展示回購,只是使解壓打勾的代碼。使用現代版本的PHP,不應該有任何不包含在您的設置中的任何內容。所以你不需要做任何服務器配置更改來使用它。

這裏是它使用的ZipArchive類的PHP文件:http://php.net/manual/en/class.ziparchive.php

沒有任何附帶的方式做你想要什麼,這是一種恥辱。所以我會將文件解壓縮到一個臨時目錄,然後使用其他功能將內容複製到您想要的位置。因此,在使用ZipArchive時,如果文件夾名稱未知,您將需要返回第一個項目以獲取文件夾名稱。如果該文件夾是已知的,即:每次都有相同的麻煩文件夾名稱,那麼您可以硬編碼該名稱。

我已經讓它返回索引中的第一項。所以,如果你總是有一個拉鍊,裏面有1個文件夾,並且該文件夾中的所有東西都可以工作。但是,如果您有一個沒有整合到1個文件夾內的所有文件的壓縮文件,它將會失敗。我添加的代碼將照顧你的問題。您需要添加更多邏輯來處理備選案例。

另外,從我們將其提取到臨時目錄進行「處理」時,您仍然會留下舊目錄。所以我包括代碼也刪除它。

注意:該代碼使用很多if來顯示處理步驟,並打印出一條消息用於測試目的。您需要修改它以滿足您的需求。

<?php 
public function copyDirectoryContents($source, $destination, $create=false) 
{ 
    if (! is_dir($source)) { 
     return false; 
    } 

    if (! is_dir($destination) && $create === true) { 
     @mkdir($destination); 
    } 

    if (is_dir($destination)) { 
     $files = array_diff(scandir($source), array('.','..')); 
     foreach ($files as $file) 
     { 
      if (is_dir($file)) { 
       copyDirectoryContents("$source/$file", "$destination/$file"); 
      } else { 
       @copy("$source/$file", "$destination/$file"); 
      } 
     } 
     return true; 
    } 
    return false; 
} 

public function removeDirectory($directory, $options=array()) 
{ 
    if(!isset($options['traverseSymlinks'])) 
     $options['traverseSymlinks']=false; 
    $files = array_diff(scandir($directory), array('.','..')); 
    foreach ($files as $file) 
    { 
     if (is_dir("$directory/$file")) 
     { 
      if(!$options['traverseSymlinks'] && is_link(rtrim($file,DIRECTORY_SEPARATOR))) { 
       unlink("$directory/$file"); 
      } else { 
       removeDirectory("$directory/$file",$options); 
      } 
     } else { 
      unlink("$directory/$file"); 
     } 
    } 
    return rmdir($directory); 
} 


$file = dirname(__FILE__) . '/file.zip';  // full path to zip file needing extracted 
$temp = dirname(__FILE__) . '/zip-temp';  // full path to temp dir to process extractions 
$path = dirname(__FILE__) . '/extracted';  // full path to final destination to put the files (not the folder) 

$firstDir = null;  // holds the name of the first directory 

$zip = new ZipArchive; 
$res = $zip->open($file); 
if ($res === TRUE) { 
    $firstDir = $zip->getNameIndex(0); 
    $zip->extractTo($temp); 
    $zip->close(); 
    $status = "<strong>Success:</strong> '$file' extracted to '$temp'."; 
} else { 
    $status = "<strong>Error:</strong> Could not extract '$file'."; 
} 

echo $status . '<br />'; 

if (empty($firstDir)) { 
    echo 'Error: first directory was empty!'; 
} else { 
    $firstDir = realpath($temp . '/' . $firstDir); 
    echo "First Directory: $firstDir <br />"; 
    if (is_dir($firstDir)) { 
     if (copyDirectoryContents($firstDir, $path)) { 
      echo 'Directory contents copied!<br />'; 
      if (removeDirectory($directory)) { 
       echo 'Temp directory deleted!<br />'; 
       echo 'Done!<br />'; 
      } else { 
       echo 'Error deleting temp directory!<br />'; 
      } 
     } else { 
      echo 'Error copying directory contents!<br />'; 
     } 
    } else { 
     echo 'Error: Could not find first directory'; 
    } 
} 
+0

請注意,我已經更新了幾次我的答案。我添加了將zip解壓縮到臨時目錄的代碼,獲取zip(您的目錄)中第一個項目的名稱,並使用該名稱將其內容複製到您想要的位置。以及通過刪除臨時目錄進行清理。 – 2015-01-26 12:56:19