2013-05-12 63 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