Na navigaci | Klávesové zkratky

Translate to English… Ins Deutsche übersetzen…

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.

Komentáře

  1. error414 #1

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

    před 10 lety
  2. louix http://www.deaddream.net/ #2

    avatar

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

    před 10 lety
  3. Martin Grames http://www.chapadlo.cz #3

    avatar

    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));
    }
    před 10 lety | reagoval [4] David Grudl
  4. David Grudl http://davidgrudl.com #4

    avatar

    #3 Martine Gramesi, 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.

    před 10 lety | reagoval [5] Martin Grames
  5. Martin Grames http://www.chapadlo.cz #5

    avatar

    #4 Davide Grudle, 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) :-(

    před 10 lety | reagoval [6] error414
  6. error414 #6

    #5 Martine Gramesi, tak to je nacase zmenit hosting, ne?

    před 10 lety
  7. David Grudl http://davidgrudl.com #7

    avatar

    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.

    před 10 lety
  8. Mayo #8

    avatar

    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…

    před 10 lety
  9. Roj http://roj.bloguje.cz #9

    avatar

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

    před 10 lety | reagoval [10] David Grudl
  10. David Grudl http://davidgrudl.com #10

    avatar

    #9 Roji, 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 :-) )

    před 10 lety
  11. Roj http://roj.bloguje.cz #11

    avatar

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

    před 10 lety
  12. xom http://pinion.xom-tom.com #12

    avatar

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

    před 10 lety
  13. Petr http://melodie.na-mobil.cz #13

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

    před 10 lety
  14. wosa http://operacesky.net/ #14

    avatar

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

    před 10 lety
  15. Jirka #15

    avatar

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

    před 10 lety
  16. Jiří Bureš http://blog.converter.cz/ #16

    avatar

    Žádná lest. Jen test.

    před 10 lety
  17. koty #17

    avatar

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

    před 10 lety
  18. mZk http://mozektevidi.ic.cz #18

    avatar

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

    před 10 lety
  19. mZk http://mozektevidi.ic.cz #19

    avatar

    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 68c2afc934fa66f3fde28b9639ef8632? Nebo co má být jako parametr?

    před 10 lety
  20. mZk http://mozektevidi.ic.cz #20

    avatar

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

    před 10 lety
  21. jenda.69 http://www.jendamusic.net #21

    avatar

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

    před 10 lety | reagoval [23] zirafka
  22. BaRacuda http://barablog.dewtex.net #22

    avatar

    Díky za tip!

    před 10 lety
  23. zirafka http://blog.zirafka.cz #23

    avatar

    #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.bloguje.cz/blogavatar.png

    před 10 lety | reagoval [24] jenda.69
  24. jenda.69 http://www.jendamusic.net #24

    avatar

    #23 zirafko, 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. :(

    před 10 lety

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