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='https://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='https://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.
Jakub Vrána :
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.
jonik555:
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ů
Jakub Vrána :
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
Michael Fanta:
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 ?
Jakub Vrána :
<?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.
SodaE:
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.
SodaE:
a bez modulu by to asi nešlo že :(
Diskuse je zrušena z důvodu spamu.