2013-05-12 58 views
5

我想使用PHP压缩(即时)tar.gz格式的目录。我知道可以使用exec或使用this code(使用ZIP格式)来完成,但我的主机不支持exec,并且没有安装PHP的zip扩展名。使用PHP实时压缩tar.gz格式的目录使用PHP

搜索互联网后,我碰到this PHP code

<?php 
// Computes the unsigned Checksum of a file’s header 
// to try to ensure valid file 
// PRIVATE ACCESS FUNCTION 
function __computeUnsignedChecksum($bytestring) { 
    for($i=0; $i<512; $i++) 
    $unsigned_chksum += ord($bytestring[$i]); 
    for($i=0; $i<8; $i++) 
    $unsigned_chksum -= ord($bytestring[148 + $i]); 
    $unsigned_chksum += ord(" ") * 8; 

    return $unsigned_chksum; 
} 

// Generates a TAR file from the processed data 
// PRIVATE ACCESS FUNCTION 
function tarSection($Name, $Data, $information=NULL) { 
    // Generate the TAR header for this file 

    $header .= str_pad($Name,100,chr(0)); 
    $header .= str_pad("777",7,"0",STR_PAD_LEFT) . chr(0); 
    $header .= str_pad(decoct($information["user_id"]),7,"0",STR_PAD_LEFT) . chr(0); 
    $header .= str_pad(decoct($information["group_id"]),7,"0",STR_PAD_LEFT) . chr(0); 
    $header .= str_pad(decoct(strlen($Data)),11,"0",STR_PAD_LEFT) . chr(0); 
    $header .= str_pad(decoct(time(0)),11,"0",STR_PAD_LEFT) . chr(0); 
    $header .= str_repeat(" ",8); 
    $header .= "0"; 
    $header .= str_repeat(chr(0),100); 
    $header .= str_pad("ustar",6,chr(32)); 
    $header .= chr(32) . chr(0); 
    $header .= str_pad($information["user_name"],32,chr(0)); 
    $header .= str_pad($information["group_name"],32,chr(0)); 
    $header .= str_repeat(chr(0),8); 
    $header .= str_repeat(chr(0),8); 
    $header .= str_repeat(chr(0),155); 
    $header .= str_repeat(chr(0),12); 

    // Compute header checksum 
    $checksum = str_pad(decoct(__computeUnsignedChecksum($header)),6,"0",STR_PAD_LEFT); 
    for($i=0; $i<6; $i++) { 
    $header[(148 + $i)] = substr($checksum,$i,1); 
    } 
    $header[154] = chr(0); 
    $header[155] = chr(32); 

    // Pad file contents to byte count divisible by 512 
    $file_contents = str_pad($Data,(ceil(strlen($Data)/512) * 512),chr(0)); 

    // Add new tar formatted data to tar file contents 
    $tar_file = $header . $file_contents; 

    return $tar_file; 
} 

function targz($Name, $Data) { 
    return gzencode(tarSection($Name,$Data),9); 
} 

header("Content-Disposition: attachment; filename=backup.tar.gz"); 
header("Content-type: application/x-gzip"); 

$getfile = file_get_contents("test.txt"); 

echo targz('test.txt', $getfile); 
?> 

这确实使用这种多个文件的工作:

header("Content-Disposition: attachment; filename=backup.tar.gz"); 
header("Content-type: application/x-gzip"); 

$getfile = file_get_contents("test.txt"); 

echo targz('test.txt', $getfile); 

$getfile2 = file_get_contents("test2.txt"); 

echo targz('test2.txt', $getfile2); 

backup.tar.gz现在是2个文件(test.txttest2.txt)。

但是我怎么用这个来下载一个目录(和子目录)呢?

我的目录是这样的:

home/ 
    file1.html 
    file2.html 
Another_Dir/ 
    file8.html 
    Sub_Dir/ 
     file19.html 

回答

5

您需要太多列出你要压缩的目录中的所有文件和目录。有一个递归的目录列表功能here。我认为结合你的代码和他的代码来完成这项工作。这样的事情:

header("Content-Disposition: attachment; filename=backup.tar.gz"); 
header("Content-type: application/x-gzip"); 

// Your other tar.gz functions... 

function compress($path = '.', $level = 0){ 
    $ignore = array('cgi-bin', '.', '..'); 
    $dh = @opendir($path); 

    while(false !== ($file = readdir($dh))){         
     if(!in_array($file, $ignore)){ 
      if(is_dir("$path/$file")){ 
       // Go to the subdirs to compress files inside the subdirs 
       compress("$path/$file", ($level+1));           
      } else { 
       $getfile = file_get_contents($path. '/' .$file); 
       // get the last dir in the $path 
       $dirs = array_filter(explode('/', $path)); 
       $dir = array_pop($dirs); 

       // if we're not in a sub dir just compress the file in root otherwise add it on the subdir... 
       if ($level < 1) { 
        echo targz($file, $getfile); 
       } else { 
        // add all top level subdirs when $level is > 2 
        for ($i = 0; $i < $level - 1; $i++) { 
         $temp = array_pop($dirs); 
         $dir = $temp.'/'.$dir; 
        } 
        echo targz($dir. '/' .$file, $getfile); 
       } 
      }           
     }          
    } 

    closedir($dh); 
} 

$dir = 'dir/to/compress'; 
if (is_file($dir)) { 
    // If it's a file path just compress it & push it to output 
    $getfile = file_get_contents($dir); 
    echo targz(basename($dir), $getfile); 
} elseif(is_dir($dir)) { 
    return compress($dir); 
} 

它适用于我。这是我的第一个贡献,希望它有帮助..

+0

我正在使用PHP框架来测试,所以'最后一行'返回'也许不必要.. – 2013-05-12 18:53:08

+0

谢谢!但是当有一个子目录('home/Another_Dir/Sub_Dir /')时,他将该文件夹移动到'backup.tar.gz'文件中的('home/Sub_Dir /'),并且他不保持正常的目录格式'家用/ Another_Dir/Sub_Dir /')。这可以修复吗? – user1480019 2013-05-12 19:48:32

+1

@GerritHoekstra我编辑了代码,以便现在应该修复。 – 2013-05-12 22:09:57