Vytváříme archívy

PHP

Archívy a komprese dat, je tu s námi již velmi dlouho. Máme taky několik možností jak data zmenšit a my si ukážeme, jak vytvořit archívy ZIP a GZip v jazyce PHP.

Vytváříme archívy

Formát ZIP vznikl již okolo roku 1989. Později byly představeny novější verze, např ZIP64, které podporují archívy větší jak 4GB. GZip, nebo GNU zip, je open source varianta ZIPu, vytvořenou pro UNIXové systémy. Dříve jsme si tento formát představili v seriálu o zrychlení načítání stránek.

ZIP

Pro možnost generování ZIP archívu v PHP využijeme třídu ZipArchive, která je dostupná jako rozšíření PHP od verze 5.2.0. Viz dokumentace

Velká výhoda této třídy je možnost přidávat soubory aktuálně generované, aniž by ve skutečnosti existovaly v souborovém systému. Pokud ovšem máme složku, kterou chceme do archívu přidat celou, musíme přidávat jednotlivé soubory a složky postupně. To si ukážeme v následujícím jednoduchém příkladu.

function addFolder($zip,$path,$folderName){
  $zip->addEmptyDir($folderName); //vytvoříme v ZIPu složku
  $currentPath = $path."/".$folderName."/"; //cesta ke složce
  $dir = opendir($currentPath); //otevřeme složku pro čtení obsahu
  
  while(($fileName = readdir($dir)) !== false) //přečteme všechny soubory a složky
  {
    if($fileName == "." || $fileName == ".."){ //aktuální a nadřazený adresář ignorujeme
      continue;
    }
    if(is_file($currentPath.$fileName)) //je na dané adrese soubor
    {
      // vložíme soubor do ZIPu
      // 1. parametr adresa k souboru v souborovém systému
      // 2. parametr relativní adresa k souboru v rámci ZIP archívu
      $zip->addFile($currentPath."/".$fileName, $folderName."/".$fileName);
    }
    else if(is_dir($currentPath.$fileName)) // je na dané adrese složka
    {
      // zavoláme funkci pro další průchod složkou
      addFolder($zip, $path, $folderName."/".$fileName);
    }
  }
}

$folderToZip = "Vouchers";

$zip = new ZipArchive();
if($zip->open($folderToZip.".zip",ZipArchive::CREATE)){ //vytvoříme nový archív
  //vložíme soubor přímo do archívu, aniž by existoval
  $zip->addFromString("info.txt", "Tento archív byl vytvořen pomocí PHP");
  //vložíme složku a všechny její podsložky
  addFolder($zip, dirname(__FILE__), $folderToZip);
  
  $zip->close();
}

Otevírání ZIP archívu

Za zmínku určitě stojí, že třída ZipArchive dokáže mnohem více, než ukazuji v příkladu. Třeba archívy také otevírat, zaheslovat a mnoho dalšího.

GZip a TAR

Dalším často používaným formátem je GZip, ačkoli by měl podporovat archívy s více soubory, běžně se to nepožívá. Proto je tady další archívní formát TAR, který vytvoří archív, ale nepoužije žádnou kompresi. Poté nad tímto souborem můžeme spustit GZip a výsledný soubor mívá příponu .tar.gz nebo .tgz.

Využijeme nyní třídu PharData, která umí mimo jiné i ZIP a BZ2. Toto rozšíření vyžaduje alespoň verzi PHP5.3 a PECL rozšíření phar2.0.

$a = new PharData('archive.tar');
// přidání souboru 2 mi způsoby
$a->addFromString("readme.txt", "Tarball vytvořen pomocí PHP");
$a->addFile('myFile.pdf');

//Nyní provedeme kompresi pomocí GZipu
$a->compress(Phar::GZ);

//Smažeme původní TAR archív, tato metoda vytvoří 2 soubory *.tar a *.tar.gz
unlink('archive.tar');

GZip jednoho souboru

Pokud ale omezení jednoho souboru nevadí, nemusíme archivaci přes TAR vůbec řešit. Můžeme využít funkcí, které jsou v PHP již téměř od počátku. Jedná se o funkce gzwrite. Následná ukázka je vhodná pouze pro malé soubory, protože se celý obsah načítá do paměti.

//otevřeme soubor, "9" na konci módu značí kompresní level
$gz = gzopen("archive.gzip", "wb9");
//načteme soubor a zapíšeme jej do archívu
gzwrite($gz, file_get_contents("voucher.pdf"));
gzclose($gz);

Pokud potřebujeme archivovat větší soubory, je lepší otevřít každý soubor zvlášť a číst a zapisovat po blocích.

K tomuto článku již není možné přidávat další komentáře