Verze ke stažení
Školení, která pořádám 
Yuhů vyzývá, abychom svůj web dali k dispozici ke stažení, v diskusi kdosi dokonce zmiňuje přímo PHP triky.
Když si chci nějaký web stáhnout, tak osobně používám wget, ale zrovna u tohoto webu to není právě jednoduché (protože obsahuje spoustu balastních odkazů kvůli reakcím na diskusní příspěvky pro uživatele s vypnutým JavaScriptem), takže verzi pro stažení dávám pokusně k dispozici.
Generuje se on-line, takže je vždy aktuální. K vytvoření archivu využívám knihovnu Archive_Tar, ale nejsem s ní příliš spokojen, protože data zapisuje do souboru a já bych je potřeboval dávat přímo na výstup. Také jsem zatím nerozchodil kompresi archivu, takže se data díky zlib.output_compression komprimují jen při přenosu.
Pro archiv platí stejné omezení jako pro web, tedy: Publikované texty můžete přetiskovat pouze se svolením autora. Ať vám tato verze slouží, připomínky uvítám v diskusi.
<?php
include "./include/lib.inc.php";
include "./include/Tar.php";
header("Content-Type: application/x-tar");
register_shutdown_function(create_function('', 'unlink($GLOBALS["tempnam"]);'));
$tempnam = tempnam($_ENV["TEMP"], "tar");
$tar = new Archive_Tar($tempnam);
$tar->create(array("default.css", "favicon.ico", "logo.gif"));
// články
$archiv = "";
$result = mysql_query("SELECT *, UNIX_TIMESTAMP(publikovano) AS publikovano_ts FROM clanky WHERE publikovano <= CURDATE() ORDER BY publikovano DESC, id DESC");
while ($row = mysql_fetch_assoc($result)) {
ob_start();
page_header($row["nadpis"]);
echo $row["zprava"];
echo "<div class='podpis'>Jakub Vrána, " . date('j.n.Y', $row["publikovano_ts"]) . ", <a href='http://php.vrana.cz/$row[url].php'>on-line</a></div>\n";
page_footer();
$tar->addString("$row[url].html", ob_get_clean());
$archiv .= "<tr><td align='right'>" . date('j.n.Y', $row["publikovano_ts"]) . "</td><td><a href='$row[url].html'><strong>" . htmlspecialchars($row["nadpis"]) . "</strong></a></td><td><a href='http://php.vrana.cz/$row[url].php'>on-line</a></td></tr>\n";
}
mysql_free_result($result);
// archiv
ob_start();
page_header("");
echo "<table cellspacing='0' cellpadding='3'>\n";
echo $archiv;
echo "</table>\n";
page_footer();
$tar->addString("index.html", ob_get_clean());
$tar->_Archive_Tar();
header("Content-Length: " . filesize($tempnam));
readfile($tempnam);
?>
Diskuse
Jan Rozehnal:
Dobré. Nemohl byste uveřejnit kód který ten archív generuje?
Tomik:
Také jsem čekal nějaký PHP trik, jak generovat z dynamických stránek, statický zabalený balíček... ;)
Určitě bych ho uvítal...
Vystavil jsem to. Není to žádný univerzální postup, ale je to ušité na míru tomuto webu. Stránky pro off-line stažení je stejně vhodné trochu upravit (nezobrazovat formulář pro vložení příspěvku do diskuse, nenabízet vyhledávání, nezobrazovat nejnovější články, ...).
Tomik:
Mnohokrát děkuji, jdu studovat... ;)
Tibor:
PHP triky čítam už dlho a možnosť stiahnutia mi pomohla. Ďakujem.
Zbavil jsem se závislosti na Archive_Tar a soubory nyní balím touto funkcí:
<?php
function tar_file($filename, $contents, $mtime)
{
$s = pack("a100a8a8a8a12a12", $filename, 0, 0, 0, decoct(strlen($contents)), decoct($mtime));
$checksum = 8*32; // space for checksum itself
for ($i=0; $i < strlen($s); $i++) {
$checksum += ord($s{$i});
}
$s .= sprintf("%06o", $checksum) . "\0 ";
$s .= str_repeat("\0", 512 - strlen($s));
$s .= $contents;
if (strlen($contents) % 512) {
$s .= str_repeat("\0", 512 - strlen($contents) % 512);
}
return $s;
}
// na konci vypsání patičky
echo pack("x512");
?>
Dodatečně mě napadlo, že místo vytváření dočasného souboru stačilo použít php://output, ale teď alespoň může být u souborů generovaných z databáze i správné datum vytvoření.
Pavel Z.:
Škoda, že tam také nejsou přibaleny komentáře. Vetšinou si v nich člověk celkem počte.
Bohužel se mi nepodařilo rozchodit
<?php fopen("compress.zlib://php://output", "wb"); ?> ani
<?php gzopen("php://output", "wb"); ?>, takže jsem komprimaci nakonec vyřešil takto:
<?php
ini_set("zlib.output_compression", false);
$print = gzencode($print);
header("Content-Type: application/x-gzip-compressed");
header("Content-Length: " . strlen($print));
echo $print;
?>
Celý výstup se ukládá do proměnné a zkomprimuje se až na konci. Výhoda spočívá v tom, že je možné poslat velikost archivu, nevýhoda zase ve zbytečně veliké paměťové náročnosti.
Možná by bylo nejlepší data ukládat přeci jen do souboru, který by zároveň sloužil jako cache.
nešlo by udělat nějaký script, kterým by se dal stáhnout celý web-pokud není řešený přes DB?? samozřejmě jen někt. typy souborů
Třeba takhle:
<?php
$zip = new ZipArchive;
$zip->open("web.zip", ZipArchive::OVERWRITE);
foreach (glob("*") as $filename) {
if (is_file($filename) && $filename != "web.zip") {
$zip->addFile($filename, $filename);
}
}
$zip->close();
header("Location: web.zip");
?>
Zamykání web.zip pro jednoduchost neřeším.
jonik:
a jak by to slo udelat na wz.cz? je tam akorat ZLIB a tohle tam bohuzel nefunguje...
Dekuju
Ahoj mohl by mi někdo poradit jak udělat to aby se mi na stránce ukázaly náhledy na všechny obrázky co obsahuje archiv ?
<?php
define("SIRKA_NAHLEDU", 100);
define("VYSKA_NAHLEDU", 100);
$zip = new ZipArchive;
$zip->open($filename);
$sirka = ceil(sqrt($zip->numFiles));
$nahledy = imagecreatetruecolor(SIRKA_NAHLEDU * $sirka, VYSKA_NAHLEDU * ceil($zip->numFiles / $sirka));
for ($i=0; $i < $zip->numFiles; $i++) {
$stat = $zip->statIndex($i);
$im = imagecreatefromjpeg("zip://" . dirname(__FILE__) . "/$filename#$stat[name]");
imagecopyresampled($nahledy, $im, SIRKA_NAHLEDU * ($i % $sirka), VYSKA_NAHLEDU * floor($i / $sirka), 0, 0, SIRKA_NAHLEDU, VYSKA_NAHLEDU, imagesx($im), imagesy($im));
imagedestroy($im);
}
?>
Předpokládá se, že všechny soubory v archivu jsou obrázky JPG. Vznikne jeden velký obrázek s náhledy, který lze zobrazit např. funkcí imagejpeg(). Tento obrázek je obvykle čtvercový, pokud bys preferoval pevnou šířku, stačí ji zadat do proměnné $sirka. Náhledy jsou zdeformované, to by se dalo vyřešit funkcí pro proporcionální zmenšení obrázků:
http://php.vrana.cz/formaty-obrazku.php.
prosímtě Jakube kde seženu pesně tenhle class "ZipArchive" ?
Pavel:
Používám Vertrigo Server pod Windows a nevím, jak tam tu třídu ZipArchive zpřístupnit.
Zkoušel jsem stáhnout php_zip.dll, přidat jej do složky ext a v php.ini připsat extension=php_zip.dll. Jenže to nepomohlo.
Co přesně je potřeba udělat? Díky komukoliv za případnou pomoc.
a bez modulu by to asi nešlo že :(