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);
?>
Jakub Vrána, Ze zákulisí, 16.12.2005, diskuse: 18 (nové: 0)

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...

ikona Jakub Vrána OpenID:

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.

ikona Jakub Vrána OpenID:

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.

ikona Jakub Vrána OpenID:

OK, dal jsem to tam.

ikona Jakub Vrána OpenID:

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.

ikona 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ů

ikona Jakub Vrána OpenID:

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 ?

ikona Jakub Vrána OpenID:


<?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" ?

ikona Jakub Vrána OpenID:

http://php.net/zip

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 :(

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.