Grafika publishing webtip.cz grafika.cz mujiPod.cz mujmac.cz fotografovani.cz printing.cz builder.cz galerie
webtip.cz
adresář  | práce  | diskuse  | redakce  | inzerce
 
 


  PHP v praxi, 26. díl - Zipujeme za pochodu
o autorovi 
poslat mailem 
tisknout článek 
aktuální rubrika 
Nechcete se stále zdržovat komprimováním souborů, které se často mění? Nechte na PHP, ať se o to postará samo.

Veselý Jan - 10.05.2002 - tutorial - Rubrika: PHP
Předchozí díl: PHP v praxi, 25. díl - Třídy a e-mail s přílohou
Seriál: 

PHP v praxi, 26. díl - Zipujeme za pochodu

Tématem dnešního dílu bude vytváření zazipovaného souboru na straně serveru. Představme si situaci, kdy jste fotograf a výsledky své práce nabízíte ke stažení. Fotografie v archivu neustále přibývají a aby návštěvníci vašich stránek nebyli příliš otráveni neustálým klikáním, nabízíte všechny své fotografie zabalené v jednom souboru. To ovšem na druhou stranu znamená značné časové ztráty pro vás - po každém updatu fotografií je znovu všechny zabalit a uploadovat na server. Proto je značně výhodné využít skript, který všechny soubory v dotyčném adresáři zabalí za vás.

Co budeme potřebovat: využijeme třídu, dodávanou s phpMyAdmin, jež má v sobě informace, jak takový zip soubor má vypadat. Stáhnout phpMyAdmin (450 kB). Soubor se nachází v adresáři "libraries" a jmenuje se "zip.lib.php".

Budeme mít celkem tři soubory - výše zmíněný zip.lib.php, dále pack.php, obsahující konkrétní funkce, a download.html, jenž bude nabízet příslušný "soubor" ke stažení.

Začneme právě download.html:

<html>
<body>
<a href="pack.php">package.zip</a>
</body>
</html>

Odkaz, jak vidíte, nemíří tedy na žádný *.zip, nýbrž na soubor pack.php. Ten si postupně rozebereme. Nejprve si ukážeme kostru bez obsahu funkcí:

<?
include("zip.lib.php");

$dir="pictures/";
$zip_name="pictures.zip";

$files=get_files($dir);
$names=$files;
$zip_content=pack_it($dir,$files,$names);
download_it($zip_content,$zip_name);
?>

Nejprve se načte příslušná knihovna zip.lib.php, pak nastavíme jméno adresáře, ve kterém budou umístěné dotyčné soubory (třeba ty fotografie) a do proměnné $zip_name umístíme informaci o názvu výsledného (staženého) souboru.

Pole $files bude obsahovat jména souborů (fotografiíí), které získáme z funkce get_files(). Protože můžeme mít jiné názvy jmen ve výsledném archivu, než jsou jména souborů, je zde ještě pole $names. V naší ukázce tuto vlastnost nevyužijeme, proto jsme $names přiřadili hodnoty z $files. Rozumné by to bylo v případě, že fotografie se jmenují 0001.jpg, 0002.jpg atp. a někde jinde máte uloženy bližší popisné informace. Pak by si návštěvník stáhl soubor, ve kterém by již byly kvetiny.jpg, hrad.jpg apod. Hned poté se použije funkce pack_it(), jež zabalí soubory do archivu a vrátí obsah souboru. Ten tedy přiřadíme proměnné $zip_content. Ukončíme zavoláním funkce download_it(), která již vyvolá nabídku ke stažení souboru v prohlížeči.

Nyní se postupně seznámíme s jednotlivými funkcemi.

function get_files($dir)
{
	$handle=opendir($dir);
	$i=0;
	while (false!==($file = readdir($handle))) 
	{
		if ($file!="."&&$file!=".."&&!is_dir($file))
		{         
			$files[$i]=$file;
			$i++;
		} 
	}
	closedir($handle); 
	return $files;
}

Funkce get_files je již několikrát ukázaný a pozměněný cyklus na získání názvů souborů. Výstupem funkce je pole $files[], obsahující tato jména.

function pack_it($dir,$files,$names)
{
	$zip = new zipfile();
	
	for($i=0;$i<count($files);$i++)
	{
		$fp=fopen($dir.$files[$i],"rb");
		$part_content=fread($fp,filesize($dir.$files[$i]));
		fclose($fp);
		
		$zip->addFile($part_content,$names[$i]);
	}

	$content=$zip->file();
	return $content;
}

Tato funkce, pack_it(), je jádrem celého skriptu. To ona pracuje se třídou v zip.lib.php. Vytvoření instance třídy zipfile se vytvoří známým zaklínadlem new název_třídy. $zip je tedy instance třídy zipfile a jako s takovou s ní teď budeme pracovat. Následuje cyklus, jehož smyslem je načíst data ze souborů a poslat je ke zpracování třídě zipfile. Načtení obsahu souboru již bylo také několikrát okomentováno, proto jen upozorním (znovu) na atribut "rb". Ten je pouze kvůli systémům, rozeznávajícím binární data (Windows), na linuxovém serveru se s tímto problémem nesetkáte. Když však pod Windows použijete pouze "r", načte se jen část souboru. Poté co otevřeme soubor a načteme jeho obsah do proměnné $part_content, použijeme metodu addFile() třídy zipfile. Ta zkomprimuje a začlení obsah souboru do budoucího zip archivu. Jeho atributy jsou $part_content, tedy obsah toho jednoho souboru, a dále jeho jméno, jež bude mít ve výsledném archivu. Toto se opakuje do doby, než se vyčerpají všechna jména souborů. Když se tak stane, zavolá se metoda file(), která vrací kompletní obsah zip archivu. To je také cílem této funkce pack_it(), takže právě tato data vrátíme příkazem return.

function save_it($content,$zip_name)
{
	$fp=fopen($zip_name,"wb");	
	fwrite($fp,$content);
	fclose($fp);
}

function download_it($content,$zip_name)
{
	header("Content-type: application/octet-stream name=$zip_name"); 
	header("Content-disposition: attachment; filename=$zip_name");
	echo $content;
}

Nakonec nabízíme zip archiv ke stažení ve funkci download_it(). Jako bonus jsem přidal ještě funkci save_it(), jež má za úkol data čistě uložit. K té již nelze moc říci, práci se soubory jsme si ukazovali již mnohokrát. Zato ve funkci download_it() je použitá ještě nikdy nezmíněná funkce header(). Ta vytváří hlavičky souborů, takže díky těmto informacím prohlížeč jednoduše pozná, že se nejedná o stránku, ale o soubor. Obsah tohoto souboru mu pošleme standardním příkazem echo. Bez hlavičky by jej ale zobrazil přímo na stránce jako změť znaků.

Nakonec opět kompletní skript, abyste jej nemuseli skládat jako puzzle.

<?
include("zip.lib.php");

$dir="pictures/";
$zip_name="pictures.zip";

function get_files($dir)
{
	$handle=opendir($dir);
	$i=0;
	while (false!==($file = readdir($handle))) 
	{
		if ($file!="."&&$file!=".."&&!is_dir($file))
		{         
			$files[$i]=$file;
			$i++;
		} 
	}
	closedir($handle); 
	return $files;
}

function pack_it($dir,$files,$names)
{
	$zip = new zipfile();
	
	if (count($files)!=count($names)) $names = $files;
	for($i=0;$i<count($files);$i++)
	{
		$fp=fopen($dir.$files[$i],"rb");
		$part_content=fread($fp,filesize($dir.$files[$i]));
		fclose($fp);
		
		$zip->addFile($part_content,$names[$i]);
	}
	$content=$zip->file();
	return $content;
}

function save_it($content,$zip_name)
{
	$fp=fopen($zip_name,"wb");	
	fwrite($fp,$content);
	fclose($fp);
}

function download_it($content,$zip_name)
{
	header("Content-type: application/octet-stream name=$zip_name"); 
	header("Content-disposition: attachment; filename=$zip_name");
	echo $content;
}

$files=get_files($dir);
$names=$files;
$zip_content=pack_it($dir,$files,$names);
download_it($zip_content,$zip_name);
?>

Veselý Jan


Hodnocení článku: -1- -2- -3- -4- -5-  Aktuální hodnocení: 2.74 (4014)

Relevantní články
Žádné články


Příspěvky do diskuse o aktuálním článku
kubijo21.02.11:56prázdné soubory
ProgDan03.04.18:20Doba generování
TimJ15.06.13:06fatal error vyřešen - jiný problém
TimJ15.06.13:13RE: fatal error vyřešen - jiný problém
TimJ15.06.12:46fatal error
Poacher01.04.8:02Seriál
Morpheus05.03.21:33Obrázky
Morpheus03.03.21:53Dotaz
Davidek20.12.20:12Zipnuti celeho adresare(stromu)
Vita13.02.1:55RE: Zipnuti celeho adresare(stromu)
Lubo12.03.15:05RE: Zipnuti celeho adresare(stromu)
Jiří Kalenský27.06.14:18Jak rozbalit GZ soubor ???
Jiří Kalenský27.06.14:39RE: Jak rozbalit GZ soubor ???
Jan Vesely27.06.20:36RE: RE: Jak rozbalit GZ soubor ???
Vladimir Bilavcik06.08.9:26Chybova hlaska
Denis14.05.16:53Funkce gzcompress() chybi
Jan Veselý14.05.17:04RE: Funkce gzcompress() chybi
Jan Veselý14.05.17:12extension=php_zlib.dll
Petr26.06.15:41RE: extension=php_zlib.dll
Vyhoň, vyliž, utři18.02.10:47RE: RE: extension=php_zlib.dll
  

 

  O vydavateli | Kontakt | Ceník reklamy | Ochrana osobních dat
©2002 Grafika Publishing. Všechna práva vyhrazena!