Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

porucha není na vašem přijímači

Kešování avatarů z gravatar.com

Před nějakou dobou jsem na La Trine zprovoznil zobrazování avatarů u komentářů. Využívám služeb serveru Gravatar, kde se můžete zaregistrovat a nahrát si vlastní ikonku. Pak už jen stačí při komentování zadat odpovídající e-mailovou adresu.

Odezva serveru Gravatar docela kolísá a stahování avatarů značně brzdí prohlížeč. Rozhodl jsem se naprogramovat nástroj, který by obrázky ukládal do cache přímo na serveru dgx.cz. Snahou bylo vytvořit co nejrychlejší a kratičký kód, který nerozhodí ani výpadek Gravataru. Nijak jsem neřešil zamykání souborů a atomicitu (nejde o kritická data).

// Cache for gravatar.com by dgx

// config
$gravatarURI = 'http://www.gravatar.com/avatar.php';
$cacheDir = dirname(__FILE__);
$expiration = 60*60*24*2; // 2 days
$emptyGIF = "GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;";

// check parameters (sanitize forbidden chars + dot)
$query = @$_SERVER['QUERY_STRING'];
$query = preg_replace('#[\x00-\x1F"*/:<>?\\\\|.]#', '', $query);
if (!$query) exit;

// is avatar cached?
$cacheFile = $cacheDir.'/'.$query;
$isCached = is_file($cacheFile);
$isExpired = $isCached && (time() - filemtime($cacheFile) > $expiration);
$img = NULL;

if (!$isCached || $isExpired)
{
    // download avatar
    $img = @file_get_contents($gravatarURI.'?'.$query);

    // put into cache
    if ($img != NULL) {
        file_put_contents($cacheFile, $img);
    }
    // for PHP4 use: fwrite(fopen($cacheFile, 'wb'), $img);
}

// load from cache or empty GIF
if ($img == NULL) {
    $img = $isCached ? file_get_contents($cacheFile) : $emptyGIF;
}

// send cache header
header("Cache-Control: max-age=$expiration");

// detect correct mimetype
if ($img[1] == 'P') {
    header('Content-Type: image/png');
} elseif ($img[1] == 'I') {
    header('Content-Type: image/gif');
} else {
    header('Content-Type: image/jpeg');
}

// send image
echo $img;

Ještě komentář: $emptyGIF se použije tehdy, pokud server gravataru neodpovídá. V kódu nejsou testovány hlavičky, neskládám žádné URL a mimetyp zjišťuji snad nejrychlejším možným způsobem.

Návod k použití

Skript umístíte do adresáře s právem zápisu a volání původní služby změníte na volání tohoto skriptu. Změní se tedy pouze URI, nic víc.

Technika je do jisté míry univerzální, můžete s drobnými úpravami kešovat i jiná data.

Karma body: 38. Líbil se vám článek?

Komentáře » přidat

  1. [1] error414: nový

    tohle jsem chtel uz jednou napsat ale nybeylo dostatek casu. Jsem rad ze se stim popral nekdo jiny.

    Posláno 10. 8. 2006 v 19.48 | Odpovědět
  2. avatar [2] louix: nový

    Nádhera, tohle se mi zdá jako dost dobře využitelý kousek PHP kódu, takže to asi na mým webu použiju (-:

    Posláno 10. 8. 2006 ve 21.15 | Odpovědět
  3. avatar [3] Martin Grames: nový

    Díky za skript.

    Vzhledem k tomu, že funkce file_get_contents a file_put_contents nepodporuje můj hosting, tak jsem si je vyhledal/napsal následovně:

    define('FILE_APPEND', 1);
    function file_put_contents1($n, $d, $flag = false) {
       $mode = ($flag == FILE_APPEND || strtoupper($flag) == 'FILE_APPEND') ? 'a' : 'w';
       $f = @fopen($n, $mode);
       if ($f === false) {
           return 0;
       } else {
           if (is_array($d)) $d = implode($d);
           $bytes_written = fwrite($f, $d);
           fclose($f);
           return $bytes_written;
       }
    }
    // načtení gravataru ze serveru
    function file_get_contents1($f) {
      $ch = curl_init();
      curl_setopt ($ch, CURLOPT_URL, $f);
      curl_setopt ($ch, CURLOPT_HEADER, 0);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      $soubor = curl_exec($ch);
      curl_close ($ch);
      return $soubor;
    }
    // načtení gravataru z cache
    function file_get_contents2($f) {
      return join ('', file ($f));
    }
    Posláno 10. 8. 2006 ve 21.37 | Odpovědět
    Na komentář reagoval [4] David Grudl
  4. avatar [4] David Grudl: nový

    [3] Martin Grames: v podstatě by stačilo místo file_put_contents (existuje od PHP 5) napsat

    fwrite(fopen($cacheFile, 'wb'), $img);

    Dal jsem to do poznámky do zdrojáku. file_get_contents by mělo fungovat od PHP 4.3.0, která byla vydaná už v roce 2002.

    Posláno 10. 8. 2006 ve 21.42 | Odpovědět
    Na komentář reagoval [5] Martin Grames
  5. avatar [5] Martin Grames: nový

    [4] David Grudl: Problém je v tom, že mám na hostingu zakázáno url file access, takže nemůžu používat file_get_contents() ani fopen pro externí skripty (soubory) :-(

    Posláno 10. 8. 2006 ve 21.55 | Odpovědět
    Na komentář reagoval [6] error414
  6. [6] error414: nový

    [5] Martin Grames: tak to je nacase zmenit hosting, ne?

    Posláno 10. 8. 2006 ve 21.58 | Odpovědět
  7. avatar [7] David Grudl: nový

    Celá věc by se dala ještě doplnit o podporu hlavičky If-Modified-Since, kterou gravatar.com podporuje, ale vzhledem k průměrné velikosti avataru 700 bajtů je to jedno.

    Posláno 10. 8. 2006 ve 22.12 | Odpovědět
  8. avatar [8] Mayo: nový

    Nič rozumné teraz nenapíšem, len to chcem vyskúšať. Dúfam, že emailová adresa, ktorú treba zadať je tá pod ktorou som si registroval avatar a nie nejaká špeciálna – vygenerovaná gravatar-om. Tento môj avatar bol pôvodne vytvorený pre last.fm, ale tentokrát som ho neokresal treshold-om. Ešte raz sorry za tento blábol…

    Posláno 10. 8. 2006 ve 23.51 | Odpovědět
  9. avatar [9] Roj: nový

    Mne to nefacha, asi se jeste nestihlo nic nakesovat :-)

    Posláno 11. 8. 2006 v 10.20 | Odpovědět
    Na komentář reagoval [10] David Grudl
  10. avatar [10] David Grudl: nový

    [9] Roj: naopak, stihlo se nakešovat, že avatar nepoužíváš. A protože expirace je nastavena na 48 hodin, tak zatím není vidět.

    (no že jsi to ty, tak jsem učinil výjimku nejvýjimkovatější a smazal cache :-) )

    Posláno 11. 8. 2006 ve 14.03 | Odpovědět
  11. avatar [11] Roj: nový

    Prázdná keš, taky keš! :-)

    Posláno 11. 8. 2006 ve 14.05 | Odpovědět
  12. avatar [12] xom: nový

    Děkuji za pěkný nápad, na podzim budu chtít gravatary u sebe také pustit.. (tato zpráva je vlastně pokusem, jak ten můj vypadá.. ;o))

    Posláno 11. 8. 2006 ve 23.42 | Odpovědět
  13. [13] Petr: nový

    Jak je to s rychlostí u curl a file get contents ?

    Posláno 13. 8. 2006 ve 13.07 | Odpovědět
  14. avatar [14] wosa: nový

    Moc díky za tenhl skript, doufám, že ho začne používat co nejvíc blogů.

    Posláno 13. 8. 2006 v 19.33 | Odpovědět
  15. avatar [15] Jirka: nový

    Díky za script – využiju :-)

    Posláno 15. 8. 2006 v 15.36 | Odpovědět
  16. avatar [16] Jiří Bureš: nový

    Žádná lest. Jen test.

    Posláno 27. 8. 2006 v 17.40 | Odpovědět
  17. avatar [17] koty: nový

    Tak to taky vyzkouším, jak svůj nový gravatar, tak kód.

    Posláno 1. 9. 2006 v 16.24 | Odpovědět
  18. avatar [18] mZk: nový

    Nevidím tam proměnou mail. Jak to funguje? U sebe na webu to mám řešené přes:
    ` $grav_url = „http://www.gra­vatar.com/ava­tar.php?grava­tar_id=“.md5($e­mail). ` a pak mám ` img src grav_url… `

    Posláno 20. 9. 2006 v 17.19 | Odpovědět
  19. avatar [19] mZk: nový

    Tak už jsem pochopil, že je to jako parametr. Ale stále to nejde. Hází mí to 43B velké soubory. Jako parametr má být ten hash? Třeba 68c2afc934fa66f3fd­e28b9639ef8632? Nebo co má být jako parametr?

    Posláno 20. 9. 2006 v 19.03 | Odpovědět
  20. avatar [20] mZk: nový

    sry, už vím :-) problém byl v avataru, nebyl zrovna dostupný tak to nefakalo (nemohlo to kešovat).. dobrej script

    Posláno 20. 9. 2006 ve 21.10 | Odpovědět
  21. avatar [21] jenda.69: nový

    Ahoj, já se fakt omlouvam za lamí otázku, v php umim fakt jenom málo.
    Chtěl bych se zeptat: jak to mam udělat, aby se mi neukázal vůbec žádnej obrázek, pokud ten uživatel nemá gravatar?
    Dal jsem si na stránky ten kód, co je nahoře, ale když uživatel gravatar nemá, tak se mi ukáže taková hnusná modrá ikona gravatar. Já bych raději chtěl, aby to v tom případě vůbec nedávalo do kódu ani ten tag „img“ s tim „žádným“ gravatarem (jako je to tady, pokud správně koukám). Díky za odpověď.

    Posláno 17. 2. 2007 ve 20.31 | Odpovědět
    Na komentář reagoval [23] zirafka
  22. avatar [22] BaRacuda: nový

    Díky za tip!

    Posláno 19. 2. 2007 v 8.08 | Odpovědět
  23. avatar [23] zirafka: nový

    [21] jenda.69: nedavno jsem resila to stejne… bohuzel jsem to zjistovala v dobe, kdy gravatar.com nejel, takze jsem nenasla, jestli to jde udelat nejak, aby nevracel zadnou ikonku, ale urcite si muzes nastavit default obrazek, ktery ti bude vracet (napriklad pruhledny 1×1px GIF, tak jak to ma tento blog.)

    Staci za URL pridat: &default=http%3A%2F%2Fwww.example.com%2Fsomeimage.jpg
    viz. http://site.gravatar.com/site/implement#…

    Jinak mam podezreni, ze dgx to tu ma stejne udelane uz davno jinak, protoze to napriklad bere i ikonky z nekdo.blogu­je.cz/blogava­tar.png

    Posláno 19. 2. 2007 ve 12.28 | Odpovědět
    Na komentář reagoval [24] jenda.69
  24. avatar [24] jenda.69: nový

    [23] zirafka: Nakonec jsem to udělal tak, jak píšeš ty…
    No a avatar jsem si nahrával v sobotu k večeru a ještě teď v pondělí odpoledne ho nemam. :(

    Posláno 19. 2. 2007 v 15.57 | Odpovědět

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře ani hlasovat

Výtah na začátek článku na první komentář

Názory čtenářů v diskusích nejsou názory provozovatele webu, a ten za jejich obsah neodpovídá.

La Trine © 2004, 2008 David Grudl – o webu
provozuje Pachollini.

Jakékoliv užití obsahu, včetně převzetí článků nebo jejich částí, je bez předchozího písemného svolení autora zakázáno.

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.