Kompresja i dekompresja archiwów ZIP to przydatna umiejętność w PHP, tym bardziej jeżeli tworzymy aplikacje, w których dochodzi do częstego pobierania czy wysłania plików. Wysyłanie lub pobieranie wielu małych plików w jednym zbiorczym archiwum jest szybsze i po prostu wygodne.

W tym tutorialu stworzymy prostą aplikację która kompresuje pliki do archiwum ZIP i rozpakowuje archiwa, które już znajdują się na serwerze. W kombinacji z aplikacją do wysyłania plików w PHP możemy zrobić bardzo użyteczne narzędzie np. do archiwizowania dokumentów lub automatyzacji częstych operacji na plikach, które wykonujemy na naszym serwerze PHP.

Z tego punktu widzenia, prawa nauki reprezentują kompresję danych w akcji.

James Gleick

Unzip – rozpakowywanie plików .zip w PHP

Nie będzie zaskoczeniem, że PHP posiada wbudowaną bibliotekę do obsługi tak elementarnej funkcjonalności jaką jest obsługa formatu ZIP. Dekompresję pliku w PHP możemy wykonać bardzo łatwo i ogranicza się do podania ścieżki do pliku i folderu w jakim mają być wypakowane pliki:

$zip = new ZipArchive;
$res = $zip->open('archiwa/archiwum.zip');
if ($res === TRUE) {
    $zip->extractTo('pliki/');
    $zip->close();
    echo "Poprawnie wypakowano pliki!";
} else {
    echo "Błąd!";
}

Na początku tworzony jest obiekt klasy ZipArchive. To wbudowana w PHP klasa odpowiedzialna za instrukcję związane z przetwarzaniem plików w formacie zip. Metoda open otwiera plik a extractTo jest odpowiedzialna za wypakowanie plików. Lokalizacja docelowa raczej powinna istnieć, bo to czy folder podawany w argumencie metody extractTo zostanie utworzony automatycznie zależy od konkretnego systemu i uprawień.

Zip – pakowanie (kompresja) plików .zip w PHP

Pora na spakowanie plików znajdujących się w danym folderze.

$zip = new ZipArchive();
if ($zip->open("archiwa/archiwum2.zip", ZipArchive::CREATE)!== TRUE) {
    echo "Błąd!";
}
else{
    $zip->addFile("pliki/plik1.jpg");
    $zip->addFile("pliki/plik2.jpg");
    $zip->addFile("pliki/plik3.jpg");
    $zip->close();
    echo "Poprawnie spakowano pliki!";
}

Oczywiście to bardzo uproszczony przykład. Tutaj ręcznie wypisujemy pliki, które chcemy spakować. W praktycznych scenariuszach będziemy chcieli spakować cały folder. Aby tego dokonać, potrzebujemy użyć dodatkowej funkcji realpath() oraz klasy RecursiveDirectoryIterator:

$root = realpath("pliki");
$zip = new ZipArchive();
$zip->open("archiwa/archiwum.zip", ZipArchive::CREATE | ZipArchive::OVERWRITE);
$pliki = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($root),
            RecursiveIteratorIterator::LEAVES_ONLY
         );
foreach ($pliki as $nazwa => $plik)
{
    if (!$plik->isDir())
    {
        $sciezka = $plik->getRealPath();
        $sciezka_relatywna = substr($sciezka, strlen($root) + 1);
        $zip->addFile($sciezka, $sciezka_relatywna);
     }
 }
 $zip->close();

W pętli foreach sprawdzamy czy ścieżka nie jest folderem – dopiero wtedy dodajemy plik. Samą jego nazwę uzyskujemy poprzez obcięcie za pomocą funkcji substr() ścieżki do folderu bazowego (root) i znaku slasha. W ten sposób skrypt skompresuje nawet najbardziej złożoną strukturę plików i odwzoruje ją w nowoutworzonym pliku w formacie ZIP.

Automatyczne pobieranie pliku po utworzeniu archiwum

Po utworzeniu pliku można wyświetlić link za pomocą echo aby użytkownik mógł pobrać go ręcznie. Możemy też wysłać utworzony do klienta za pomocą znanej nam już z innego artykułu techniki zmiany nagłówków i funkcji readfile():

$nowe_archiwum = "archiwa/archiwum.zip";
$nowa_nazwa = "pobieranie.zip";
header("Content-type:application/zip");
header("Content-Length: " . filesize($nowe_archiwum));
header('Content-Disposition: attachment; filename="'.$nowa_nazwa.'"');
readfile($nowe_archiwum);
exit;

Wówczas po uruchomieniu skryptu plik zostanie wygenerowany i od razu będzie gotowy do pobrania. Zachowanie przeglądarki jest zupełnie takie jakbyśmy kliknęli w link prowadzący do gotowego pliku.

Alternatywna metoda: polecenia systemowe

Pakowanie folderów i rozpakowywanie gotowych archiwów można wykonać za pomocą systemowych poleceń. Rozpakowanie wykonujemy wówczas za pomocą:

system("unzip archiwa/archiwum.zip");

Pakowanie też można wykonać tą metodą:

system("zip -r archiwum.zip archiwa/*");

Problem z tymi instrukcjami polega na tym, że nie każdy hosting daje dostęp do tych funkcji. Dużo pewniejszym i bardziej niezawodnym rozwiązaniem jest korzystanie z rozszerzenia ZipArchive.

Podsumowanie

Przykład kompresji i dekompresji plików w PHP ponownie pokazuje jak łatwo można w tym języku wykonać przydatne operacje bez konieczności ładowania specjalnych narzędzi czy bibliotek. Możliwość wykonania archiwów może mieć wiele zastosowań począwszy od tworzenia nowych funkcjonalności w naszej aplikacji jak i wspierania działań administracyjnych takich jak tworzenie kopii zapasowych czy migracji stron. Więcej przykładów i możliwości omawianych klas można znaleźć w źródłach.

Źródła

Oceń artykuł na temat: Pakowanie i rozpakowywanie plików ZIP w PHP
Średnia : 4.9 , Maksymalnie : 5 , Głosów : 11