2011-03-30 89 views
2

我有名爲「數據」的文件夾。這個「data」文件夾包含一個「filecontent.txt」文件和另一個名爲「Files」的文件夾。 「文件」文件夾包含一個「info.txt」文件。 所以它是一個文件夾結構內的文件夾。如何壓縮一個文件夾並使用php下載它?

我必須壓縮此文件夾「數據」(使用PHP)以及其中的文件和文件夾,並下載壓縮文件。

我試過可用的例子http://www.php.net/manual/en/zip.examples.php 這些例子沒有奏效。我的PHP版本是5.2.10

請幫忙。

我寫過這段代碼。

<?php 
$zip = new ZipArchive; 
if ($zip->open('check/test2.zip',ZIPARCHIVE::CREATE) === TRUE) { 
    if($zip->addEmptyDir('newDirectory')) { 
     echo 'Created a new directory'; 
    } else { 
     echo 'Could not create directory'; 
    } 
    $zipfilename="test2.zip"; 
    $zipname="check/test2.zip"; 

    header('Content-Type: application/zip'); 
    header('Content-disposition: attachment; filename=check/test1.zip'); //header('Content-Length: ' . filesize($zipfilename)); 
    readfile($zipname); //$zip->close(); } else { echo failed'; 
} 
?> 

文件下載,但無法解壓縮

+2

你是什麼意思由*沒有工作做*? – fabrik 2011-03-30 09:15:15

+0

可能重複的[如何使用PHP壓縮整個文件夾](http://stackoverflow.com/questions/4914750/how-to-zip-a-whole-folder-using-php) – mario 2011-03-30 09:26:43

+0

我的意思是,當我跑腳本在url,沒有錯誤發生,但壓縮或下載不會發生。我不知道發生了什麼問題。 – Sangam254 2011-03-30 09:43:17

回答

1

見鏈接的副本。另一個經常被忽視且特別懶惰的選項是:

exec("zip -r data.zip data/"); 
header("Content-Type: application/zip"); 
readfile("data.zip"); // must be a writeable location though 
+0

懶惰?放入一些平臺檢測並將其稱爲簡短且甜蜜:D – Christian 2011-03-30 09:30:19

+0

在大多數託管服務器上,由於安全原因,PHP中的exec被禁用。 – 2011-03-30 09:31:31

+0

@FractalizeR:我不會稱他們爲「最」,而是「低端」。而且這也不是一個很好的安全方法的指示。 (我還沒有看到一個你不能通過將你自己的PHP解釋器放入cgi-bin來繞過它的問題。) – mario 2011-03-30 09:33:11

4

您需要遞歸添加目錄中的文件。像這樣(未經):

function createZipFromDir($dir, $zip_file) { 
    $zip = new ZipArchive; 
    if (true !== $zip->open($zip_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) { 
     return false; 
    } 
    zipDir($dir, $zip); 
    return $zip; 
} 

function zipDir($dir, $zip, $relative_path = DIRECTORY_SEPARATOR) { 
    $dir = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; 
    if ($handle = opendir($dir)) { 
     while (false !== ($file = readdir($handle))) { 
      if (file === '.' || $file === '..') { 
       continue; 
      } 
      if (is_file($dir . $file)) { 
       $zip->addFile($dir . $file, $file); 
      } elseif (is_dir($dir . $file)) { 
       zipDir($dir . $file, $zip, $relative_path . $file); 
      } 
     } 
    } 
    closedir($handle); 
} 

然後調用$zip = createZipFromDir('/tmp/dir', 'files.zip');

爲了獲得更大的勝利,我建議在SPL讀了DirectoryIteratorhere

+0

謝謝你的代碼。我嘗試過這個。但是當我在url上運行腳本時,沒有發生錯誤,但是不會發生壓縮或下載。我不知道發生了什麼問題.. – Sangam254 2011-03-30 09:44:20

+0

代碼壓縮文件,但不發送它。您需要設置適當的頭文件(請參閱其他答案),然後調用'fpassthru($ zip_file)' – chriso 2011-03-30 09:55:43

2

我必須做同樣的事情了幾天以前,這就是我所做的。

1)檢索文件/文件夾結構並填充項目數組。每個項目是一個文件或一個文件夾,如果它是一個文件夾,以相同方式檢索其內容。

2)解析該數組並生成zip文件。

把我的代碼如下,當然,你將不得不依賴於你的應用程序是如何製作的,以適應它。

// Get files 
$items['items'] = $this->getFilesStructureinFolder($folderId); 

$archiveName = $baseDir . 'temp_' . time(). '.zip'; 

if (!extension_loaded('zip')) { 
    dl('zip.so'); 
} 

//all files added now 
$zip = new ZipArchive(); 
$zip->open($archiveName, ZipArchive::OVERWRITE); 

$this->fillZipRecursive($zip, $items); 

$zip->close(); 

//outputs file 
if (!file_exists($archiveName)) { 
    error_log('File doesn\'t exist.'); 
    echo 'Folder is empty'; 
    return; 
} 


header("Pragma: public"); 
header("Expires: 0"); 
header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
header("Cache-Control: private", false); 
header("Content-Type: application/zip"); 
header("Content-Disposition: attachment; filename=" . basename($archiveName) . ";"); 
header("Content-Transfer-Encoding: binary"); 
header("Content-Length: " . filesize($archiveName)); 
readfile($archiveName); 

//deletes file when its done... 
unlink($archiveName); 

方法用於填充&解析:

/** 
* 
* Gets all the files recursively within a folder and keeps the structure. 
* 
* @param int  $folderId The id of the folder from which we start the search 
* @return array $tree  The data files/folders data structure within the given folder id 
*/ 
public function getFilesStructureinFolder($folderId) { 
    $result = array(); 

    $query = $this->db->query('SELECT * FROM xx WHERE deleted = 0 AND status = 1 AND parent_folder_id = ? ORDER BY name ASC', $folderId); 

    $folders = $query->result(); 

    foreach($folders as $folder) { 
     $folderItem = array(); 
     $folderItem['type']  = 'folder'; 
     $folderItem['obj']  = $folder; 
     $folderItem['items'] = $this->getFilesStructureinFolder($folder->id); 
     $result[]    = $folderItem; 
    } 

    $query = $this->db->query('SELECT * FROM xx WHERE deleted = 0 AND xx = ? AND status = 1 ORDER BY name ASC', $folderId); 

    $files = $query->result(); 

    foreach ($files as $file) { 
     $fileItem = array(); 
     $fileItem['type'] = 'file'; 
     $fileItem['obj'] = $file;  
     $result[]   = $fileItem; 
    } 

    return $result; 
} 

/** 
* Fills zip file recursively 
* 
* @param ZipArchive $zip  The zip archive we are filling 
* @param Array   $items  The array representing the file/folder structure 
* @param String  $zipPath Local path within the zip 
* 
*/ 
public function fillZipRecursive($zip, $items, $zipPath = '') { 
    $baseDir = $this->CI->config->item('xxx'); 

    foreach ($items['items'] as $item) { 

     //Item is a file 
     if ($item['type'] == 'file') { 
      $file = $item['obj']; 
      $fileName = $baseDir . '/' . $file->fs_folder_id . '/' . $file->file_name; 

      if (trim($file->file_name) == '' || !file_exists($fileName)) 
       continue; 

      $zip->addFile($fileName, $zipPath.''.$file->file_name); 
     } 

     //Item is a folder 
     else if ($item['type'] == 'folder') { 
      $folder  = $item['obj']; 

      $zip->addEmptyDir($zipPath.''.$folder->name); 

      //Folder probably has items in it! 
      if (!empty($item['items'])) 
       $this->fillZipRecursive($zip, $item, $zipPath.'/'.$folder->name.'/'); 
     } 
    } 
} 
+0

我已經寫了這段代碼。 $ zip = new ZipArchive; if($ zip-> open('check/test2.zip',ZIPARCHIVE :: CREATE)=== TRUE){ if($ zip-> addEmptyDir('newDirectory')){ echo'創建一個新目錄「; } else { echo'Could not create directory'; } $ zipfilename =「test2.zip」; $ zipname =「check/test2.zip」; header('Content-Type:application/zip'); \t header('Content-disposition:attachment; filename = check/test1.zip'); \t // header('Content-Length:'。filesize($ zipfilename)); \t readfile($ zipname); // $ zip->接近(); }其他{回聲失敗'; } 文件已下載但無法解壓 – Sangam254 2011-03-30 10:25:25

+0

如果您需要調試信息,您可以使用error_log(),那麼在使用標頭之前不應使用echo。 – Deratrius 2011-03-30 11:10:58

1

使用TbsZip類來創建一個新的ZIP文件。 TbsZip很簡單,它不使用臨時文件,不使用zip EXE,它沒有依賴關係,並具有下載功能,可以將存檔作爲下載文件進行刷新。

你只需要在文件夾樹下循環,並添加存檔中的所有文件,然後進行沖洗。

代碼例如:

$zip = new clsTbsZip(); // instantiate the class 
$zip->CreateNew(); // create a virtual new zip archive 
foreach (...) { // your loop to scann the folder tree 
    ... 
    // add the file in the archive 
    $zip->FileAdd($FileInnerName, $LocalFilePath, TBSZIP_FILE); 
} 
// flush the result as an HTTP download 
$zip->Flush(TBSZIP_DOWNLOAD, 'my_archive.zip'); 

文件中存檔加入將依次沖洗()方法的過程中被壓縮。所以你的存檔可以包含大量的子文件,這不會增加PHP的內存。

+0

喜歡它!使用起來非常簡單,適用於GoDaddy或OVH等共享(廉價)託管服務 – 2014-03-19 12:22:46

4

=========對我來說,唯一的解決辦法! ! !==========

將所有子文件夾和子文件及其結構:

<?php 
$the_folder = 'path/foldername'; 
$zip_file_name = 'archived_name.zip'; 


$download_file= true; 
//$delete_file_after_download= true; doesnt work!! 


class FlxZipArchive extends ZipArchive { 
    /** Add a Dir with Files and Subdirs to the archive;;;;; @param string $location Real Location;;;; @param string $name Name in Archive;;; @author Nicolas Heimann;;;; @access private **/ 

    public function addDir($location, $name) { 
     $this->addEmptyDir($name); 

     $this->addDirDo($location, $name); 
    } // EO addDir; 

    /** Add Files & Dirs to archive;;;; @param string $location Real Location; @param string $name Name in Archive;;;;;; @author Nicolas Heimann 
    * @access private **/ 
    private function addDirDo($location, $name) { 
     $name .= '/'; 
     $location .= '/'; 

     // Read all Files in Dir 
     $dir = opendir ($location); 
     while ($file = readdir($dir)) 
     { 
      if ($file == '.' || $file == '..') continue; 
      // Rekursiv, If dir: FlxZipArchive::addDir(), else ::File(); 
      $do = (filetype($location . $file) == 'dir') ? 'addDir' : 'addFile'; 
      $this->$do($location . $file, $name . $file); 
     } 
    } // EO addDirDo(); 
} 

$za = new FlxZipArchive; 
$res = $za->open($zip_file_name, ZipArchive::CREATE); 
if($res === TRUE) 
{ 
    $za->addDir($the_folder, basename($the_folder)); 
    $za->close(); 
} 
else { echo 'Could not create a zip archive';} 

if ($download_file) 
{ 
    ob_get_clean(); 
    header("Pragma: public"); 
    header("Expires: 0"); 
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
    header("Cache-Control: private", false); 
    header("Content-Type: application/zip"); 
    header("Content-Disposition: attachment; filename=" . basename($zip_file_name) . ";"); 
    header("Content-Transfer-Encoding: binary"); 
    header("Content-Length: " . filesize($zip_file_name)); 
    readfile($zip_file_name); 

    //deletes file when its done... 
    //if ($delete_file_after_download) 
    //{ unlink($zip_file_name); } 
} 
?> 
相關問題