2011-03-30 82 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); } 
} 
?> 
相关问题