Generovani vice variant obrazku [best practice]

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Felix
Nette Core | 1196
+
+1
-

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:

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

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
+
+1
-

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)
  1. 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)
  2. 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.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
+
0
-

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
+
+1
-

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
+
0
-

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
+
0
-

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
+
0
-

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

Felix
Nette Core | 1196
+
0
-

Osobne jsem tusil, ze to povetsinou bude 2.2. Slo mi o to, jestli jeste neni nejaky jinaci zpusob, ktery jsem neuvedl.

Prace s obrazkama je podle me velke tema a je to potreba vsude. Nebylo by od veci, kdybychom spolecne vytvorilo nejaky addon. Co myslite?

Vojtěch Dobeš
Gold Partner | 1316
+
+7
-

Dovolím si podotknout, že dotblue/nette-webimages toto whitelistování podporuje :).

Filip Procházka
Moderator | 4668
+
0
-

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
+
0
-

@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
+
0
-

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
+
0
-

@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
+
0
-

.jpg, .png … Když pak budeš chtít použít opravdu existující obrázek, tak to nepůjde.

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

@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
+
0
-

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)

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

@JiříNápravník Getter přidán v masteru.

Jiří Nápravník
Člen | 710
+
0
-

@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
+
0
-

@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
+
0
-

@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
+
0
-

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
+
0
-

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
+
+2
-

Pak je řešením umožnit, aby <id> mohlo obsahovat lomítka (vypnout rawurldecode pro onen parametr).

iguana007
Člen | 970
+
0
-

Ok, díky za nakopnutí, o víkendu to vyzkouším ;)

Jiří Nápravník
Člen | 710
+
+1
-

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
+
0
-

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

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

@MartinitCZ Omlouvám se, ale stále nerozumím.

akadlec
Člen | 1326
+
0
-

@MartinitCZ ale ono se ti všechny obrázky netahají přes index.php ale jen ty co neexistují, takže třeba foo.jpg ti ještě neexistuje a tak ti je extension vygeneruje a uloží do webdiru, takže při příštím requestu už to jde přímo na obrázek mimo nette.

David Matějka
Moderator | 6445
+
+5
-

@MartinitCZ radek

RewriteCond %{REQUEST_FILENAME} !-f

zajistuje, ze se budou na index smerovat pouze soubory, ktere neexistuji na disku

akadlec
Člen | 1326
+
+1
-

A jak to v dotblue vypadá s podporou PNG v generátoru? Mít tam natvrdo JPG mi nepříjde moc košér :(

BTW: co to ještě nějak učesat? Je to takové nějaké moc splácané, né žeby to něčemu vadilo jen mě to opticky rozčiluje ve stromové struktůře ;)

looky
Člen | 99
+
0
-

@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
+
+1
-

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
+
0
-

@akadlec Kdyžtak prosím řešme diskusi ohledně dotblue/nette-webimages v jeho issues, a ne v tomto vlákně.