Generovani vice variant obrazku [best practice]
- Felix
- Nette Core | 1196
Zdravim,
Generovani nahledu a dalsich verzi se uz nejspis nekolikrat resilo. Rad bych zjistil, jake techniky pouzivate. Zkusim popsat, takove ktere me napadaji.
Resime to vesmes u kazdeho projektu, tak me to zajima pomerne dost.
Napady:
- Generovani pri nahrani
Mam klasicky formular a pri nahrani se mi vytvori X variant.
- + Jednoduche pouziti
- – Vsechno miniatury vytvarim naraz
- – Musim to vsechno ulozit do DB?!, pripadne pouzivat nejaky obecny prefix
- – Co kdyz mi pribude nejaka dalsi varianta..
- On-the-fly generovani
Mam nejakou sluzbu, ktera mi vytvori miniaturu jakou zrovna potrebuju.
$service->image($path, $width, $height, $flags, ..);
2.1) Vse zpracovava router
Vsechny pozadavky jdou na aplikaci a ta vraci prislusny obrazek.
$image->send(...);
+/-
- To nejspis nebude nejrychlejsi
- Zbytecne to zatezuje aplikaci, ikdyz varianta uz existuje
2.2) Varianty se tvori pres URL
- example.com/storage/img_WIDTHxHEIGHT.jpg
Kdyz tedy obrazek existuje, tak ho server vrati, kdyz ne, tak se to presmeruje na aplikaci a ona danou variantu vytvori.
Otazky
- Co delat kdyz se zmeni original? To budou ty nahledy neaktualni.
- Jak poznat, ktere varianty jsou pouzivane a ktere ne.
Priklady hotovych reseni:
- https://github.com/…e/master/src
- https://github.com/2rec/Images
- https://github.com/f3l1x/Thumbator
- https://github.com/brabijan/images
- https://github.com/…nette-images
A tedka otazka, ktera plati pro vsechny.
- Jak vyresit responsivni varianty. Na desktop chci 800×600, na tablet 600×400, na mobil 300×200 [priklad].
Urcite existuji dalsi postupy, jak to resite vy? Diky za nazory ;-)
- japlavaren
- Člen | 404
za seba pouzivam variantu 2.2 Varianty se tvori pres URL.
ukladam si original (zmenseny na nejaku rozumnu velkost) a nasledne k nemu
miniatury, ktore ak neexistuju sa vytvoria pri prvom poziadavku.
k tvojim otazkam:
- mam 2 typy obrazkov. galeria – maju id podla autoincrement v db – ak sa obrazok zmeni, stary zmazem z disku i db a vytvorim novy s novym id. (na nazanie z disku je uzasny Finder a ziskanie suborov podla masky)
- druhy typ obrazkov sa moze menit. na tie pouzivam helper, ktory k nazvu prida ?123 – posledne 3 znaky z filemtime. cize ak sa subor zmeni prehiadac je donuteny natiahnu novy… (rovnaky sposob pouzivam i na js a css subory)
- na generovanie obrazkov mam v configu pole povolenych rozmerov. mozno som len paranoidny ale nechcem aby si niekto generoval co ho napadne a tym mi vytazoval server (a spinil disk)
- ako spoznat, co sa pouziva a co nie je problem na ktory nepoznam riesenie. raz za cas (raz za rok) vlezem na server a premazem vsetky miniatury a tie, ktore sa pouzivaju si server automaticky nageneruje znovu, ked ich bude potrebovat
na responzivne varianty ti neviem odpovedat. snazim sa pouzivat nejaku strednu velkost obrazku, ktoru potom u uzivatela v prehliadaci zmensujem/zvecsujem (attr width/height) v zavislosti na potrebnej velkosti
Editoval japlavaren (3. 9. 2014 20:07)
- Filip Procházka
- Moderator | 4668
2.2) Varianty se tvori pres URL
Tohle je v podstatě jediná použitelná varianta.
Co delat kdyz se zmeni original? To budou ty nahledy neaktualni.
- Vymysli si konveci pojmenování a podle ní dokážeš při uploadu obrázků smazat jeho náhledy
- Nebo ukládej do databáze soubory kam generuješ náhledy k tomu obrázku
- Nebo nepřepisuj obrázek ale vždy nahrávej nový (nové id, nový hash, …) díky tomu to bude jedno, protože odkazovat budeš na nový obrázek z webu, jenom prostě bude stále existovat i ten starý
Jak poznat, ktere varianty jsou pouzivane a ktere ne.
Není to jedno?
Priklady hotovych reseni:
Osobně se mi nejvíc líbí tohle, protože je založené na mém řešení :D
Jak vyresit responsivni varianty. Na desktop chci 800×600, na tablet 600×400, na mobil 300×200 [priklad].
Myslím že se to dělá nějak takto
<img n:img="filename.jpg, 300x200"
data-img-tablet="{img filename.jpg, 600x400}"
data-img-desktop="{img filename.jpg, 800x600}">
A pak si vyrobíš nějakej document.ready
callback, který
pomocí image preloadingu nahradí za ty větší varianty.
Super na tom je, že ten malej obrázek se načte rychle, ten velkej se načte na pozadí a pak se nahradí, takže uživatel uvidí rozmazanej obrázek (na desktopu) a pak mu tam přeblikne ten ostrej a nemělo by to dělat takovej ten hnusnej efekt když se to načítá odshora dolů :)
- japlavaren
- Člen | 404
Filip Procházka napsal(a):
riesenie s data attr verzii obrazkov sa mi paci, mno by si sa mohol s nami podelit o to makro
- David Matějka
- Moderator | 6445
Jak vyresit responsivni varianty. Na desktop chci 800×600, na tablet 600×400, na mobil 300×200 [priklad].
https://www.youtube.com/watch?…
jinak taky pouzivam 2.2
- petr.pavel
- Člen | 535
Varianta 2) Zmenšené kopie ukládám do Nette Cache s odkazem na původní soubor. To mi zajistí, že když se změní, invalidují (smažou) se i kopie.
Hlavně používej ETag / lastModified, ať použiješ cache prohlížeče a zbytečně nestahuješ, co nemusíš.
Editoval petr.pavel (3. 9. 2014 23:56)
- enumag
- Člen | 2118
Filip Procházka napsal(a):
2.2) Varianty se tvori pres URL
Tohle je v podstatě jediná použitelná varianta.
Priklady hotovych reseni:
Osobně se mi nejvíc líbí tohle, protože je založené na mém řešení :D
Pokud mi něco neuniklo tak tenhle addon využívá řešení 2), nikoli 2.2).
EDIT: Mimochodem osobně mi 2.2) přijde nepoužitelná protože musíš kontrolovat zda žádaný obrázek je v množně rozměrů které podporuješ jinak ti hrozí zaplnění disku balastem. Jediná použitelná mi připadá možnost 2) kterou také používám.
Pokud jde o responzivitu, rád bych pro Nette viděl addon, který by pracoval s picturefillem.
Editoval enumag (4. 9. 2014 1:07)
- Filip Procházka
- Moderator | 4668
enumag napsal(a):
Pokud mi něco neuniklo tak tenhle addon využívá řešení 2), nikoli 2.2).
Máš pravdu, trošku se projevila moje schizofrenie, někde používám
brabijan/images
(na menší projekty) a v Damejidlo používáme
„2.2)“. S tím „2.2)“ je maličko víc práce, ale je to
efektivnější.
EDIT: Mimochodem osobně mi 2.2) přijde nepoužitelná protože musíš kontrolovat zda žádaný obrázek je v množně rozměrů které podporuješ jinak ti hrozí zaplnění disku balastem.
Stačí si whitelistovat několik velikostí, to mi nepřijde jako takový nepřekonatelný problém :)
- Vojtěch Dobeš
- Gold Partner | 1316
Dovolím si podotknout, že dotblue/nette-webimages
toto whitelistování podporuje :).
- Filip Procházka
- Moderator | 4668
Spíš než vytvářet další bychom měli doladit nějaký existující a jak tak koukám na ten dotblue, tak taky není vůbec špatný :)
- Jiří Nápravník
- Člen | 710
@vojtech.dobes wow, super. něco takového jsme přesně hledal! Jen jeden dotaz, dají se nějak vytáhnout ty whitelistovaný velikosti? Potřebuji to, když chci mazat staré obrázky, abych smazal všechyn velikosti
- MartinitCZ
- Člen | 580
U řešení od @vojtech.dobes bych hned zrušil přidávání
koncovky obrázku, aby se nemusel upravovat .htaccess.
Stejně jako to má placehold.it
- Vojtěch Dobeš
- Gold Partner | 1316
@JiříNápravník Aktuálně nedají, ale doplním getter :).
@MartinitCZ Jakýkoliv pull request nebo i jen otevření issue je vítáno :). Co myslíš tím přidáváním koncovky obrázku?
- MartinitCZ
- Člen | 580
.jpg, .png … Když pak budeš chtít použít opravdu existující obrázek, tak to nepůjde.
- Vojtěch Dobeš
- Gold Partner | 1316
@MartinitCZ Kde se tak podle tebe tomu děje?
dotblue/nette-webimages
by mělo podporovat
ukládání/načítání obrázků z libovolných adres – zaleží jen na
nadefinovaných routách.
- Felix
- Nette Core | 1196
Zkousel jsem ten addon od @vojtech.dobes a opravdu se pekne pouziva.
Par veci ceho jsem si vsiml:
- lze generovat jenom JPG obrazky
- kdyz to spustim na localhost/test-images/www tak mi to pak uklada zvlaste
obrazky
- konkretne do localhost/test-images/www/storage/test-images/www/test-300×200.jpg
- ale URL je localhost/test-image/www/storage/test-300×200.jpg
- takze request jde vzdy pres nette router a pote na obrazek, ale to by slo nejak potunit
- edit: je to v nastaveni mask route (AHA :-))
Jinak musim rict, ze supr. Zkusim si s tim trochu pohrat a treba pridat nejaky ty srcsety atd.
Editoval Felix (4. 9. 2014 19:21)
- Jiří Nápravník
- Člen | 710
@vojtech.dobes diky, to bylo rychle:-)
Jinak jestli o to stojis, tak co jsem si vsiml ja, co mi chybi zatim nebo neni uplne idealni:
- macro – je podle mě divné, chtít jenom <id>, mám v databázi uloženou celou cestu k obrázku a tak by asi bylo lepší vypisovat přímo ji.
- stalo by za zvazeni v tech rules, jestli to nejde udelat nejak lepe, kdyz je v aplikaci vice ruznych obrazku. Napriklad mam obrazky, ktere budou v anotacich – tam budou moci byt treba dva rozmery a pak obrazky co budou v galerii a tam bude pet rozmeru. Ted ty pravidla funguji pro vsechny. Ono mozna i jestli by nestal za zvazeni pristup, kazdy provider bude mit definovany svoje rozmery a svoje routy. Ale je pravda, ze se to da osetrit i primo v tom samotnem provideru a poslat to tak na dalsi…
- Vojtěch Dobeš
- Gold Partner | 1316
@JiříNápravník Přesně jak říkáš, Provider
si to
může dále limitovat a být ještě striktnější. Stejně tak
<id>
je velmi abstraktní, může to být klidně cesta :).
Aspoň myslím, že by s tím neměl být problém – nebo jsi měl na mysli
něco jiného?
- iguana007
- Člen | 970
@vojtech.dobes Vypadá to dobře, asi to taky zkusím :)
Chápu to dobře, že pokud nechci cpát všechny vygenerované obrázky do jedné složky (v několika aplikacích mám již statisíce originálů, které potřebuji resizovat), tak si musím upravit ten provider (https://github.com/…rovider.php)
- Vojtěch Dobeš
- Gold Partner | 1316
Ukládání vygenerovaných obrázků záleží na routách. Uložení
originálů záleží na aplikaci, a Provider
pak musí znát (nebo
se od někoho dovědět), kde jsou uloženy.
Pokud nechceš všechny vygenerované velikosti ve stejné složce, neměl by být problém s routou tohoto typu:
webimages:
routes:
- 'images/<width>/<height>/<id>.jpg'
Provider
by podle <id>
měl najít originál
a vrátit instanci Nette\Utils\Image
, o jejíž uložení už se
postará celý addon – a uloží tu instanci právě na URL, na kterou
směřoval požadavek, tudíž podle matchnuté routy.
Editoval vojtech.dobes (5. 9. 2014 9:19)
- iguana007
- Člen | 970
To je právě to, že já tu strukturu řeším trošku jinak, protože většina těch obrázků bude mít stejné velikosti thumbnails, takže by to v mém případě znamenalo zase obrovské množství souborů v jedné složce. Obdobnou strukturu, které bych chtěl dosáhnout u thumbnails řeším i u těch originálů, kterým při uploadu generuju název ve formě hashe, ze kterého si vezmu první 4 písmena a podle nich vytvořím cestu/složky:
Soubor abcdefghijklhash.jpg se uloží do cesty: /upload/a/b/c/d/abcdefghijklhash.jpg
náhledy k tomuto obrázku jsou potom uloženy v cestě /thumbs/a/b/c/d/abcdefghijklhash/
Editoval iguana007 (5. 9. 2014 9:26)
- Vojtěch Dobeš
- Gold Partner | 1316
Pak je řešením umožnit, aby <id>
mohlo obsahovat
lomítka (vypnout rawurldecode
pro onen parametr).
- Jiří Nápravník
- Člen | 710
Já dokonce ani lomítka nevypínám a mám routu takhle:
- routes
- ‚<id pictures/article/.*>-<width [0–9]+>x<height [0–9]+>.jpg‘
používám mám pak v té adrese lomítka, jen ne a/b/c , ale ROK/MESIC/DEN
@vojtech.dobes Teď asi moc nechápu. Já myslel, že to <id> musí být shodné s tím co mám v routě. Tudíž tam dle mě prostě narvat celou cestu včetně koncovky nemohu. Mám proste v databazi něco na styl: pictures/article/2012/02/05/obrazek.jpg a muzu do toho makra dat jen pictures/article/2012/02/05/obrazek – bez koncovky. Nebo mi něco uniká?
- MartinitCZ
- Člen | 580
@vojtech.dobes Ano na nadefinovaných routách, ale proč tahat všechny .jpg přes index.php, když by se to dalo udělat tak, aby se nemusel upravovat výchozí Nette .htaccess.
- David Matějka
- Moderator | 6445
@MartinitCZ radek
RewriteCond %{REQUEST_FILENAME} !-f
zajistuje, ze se budou na index smerovat pouze soubory, ktere neexistuji na disku
- looky
- Člen | 99
@akadlec Mám rozpracovaný velký česací PR (říkám mu hřeben). Bugfixy, struktura, testy.. Ale bude mi to ještě nějakou dobu trvat, není teď nějak moc času.
A pokud jde o formáty, IIRC @vojtech.dobes tam má rozdělanou branch, ale nekoukal jsem v jakém je stavu.
Editoval looky (10. 9. 2014 21:15)
- akadlec
- Člen | 1326
oukej, klidně počkám ;)
btw, co takhle ještě odstranit tu výjimku co se vyhodí když není definován žáden provider? Rád bych ty providery definoval přímo v ext modulu než v neonu. Teď jsem to zkusil vyřešit že tam v neonu hodím fakeProvider jenže ten je jako první takže následně registrovaný požadovaný provider se k processingu nedostane :(
- Vojtěch Dobeš
- Gold Partner | 1316
@akadlec Kdyžtak prosím řešme diskusi ohledně
dotblue/nette-webimages
v jeho issues, a ne v tomto vlákně.