Obrázek – vykreslení v šabloně

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
22
Člen | 1478
+
0
-

Potřeboval bych nějakým způsobem dostat obrázek do šablony, ale nedaří se mi to:

$this->template->image = Image::fromFile($path);
<img src="{!$image}">

jde o to, že obrázek mám v adresáři, který není z venku dostupný a nemůžu použít jen cestu k němu.

Editoval 22 (2. 3. 2011 8:16)

wopice
Člen | 21
+
0
-

Mohl bys vytvořit jeden presenter, který bude místo stránky vracet obrázek. A v šabloně, kde potřebuješ ten obrázek vykreslit, na něj odkazovat pomocí plink.

Editoval wopice (2. 3. 2011 18:41)

jtousek
Člen | 951
+
0
-

To je pomalé, protože se pro načtení obrázku spouští celé Nette. Jednu dobu jsem takhle obrázky řešil a nakonec jsem to přepsal.

Dát to do src je dobrá možnost. Asi bych si na to napsal nějaký šablonový helper nebo makro. Problém je, že v těch šablonách nikdy nedokážu rozhodnout, co z těch dvou bych měl použít a proč. Mohl by mi to někdo ze zkušenějších objasnit?

Editoval jtousek (2. 3. 2011 9:48)

norbe
Backer | 405
+
0
-

Helper si představ jako funkci, který prostě předáš něco na vstup a při každým renderování šablony se volá. Helper má tedy přístup k vlastnímu obsahu proměnných.

Makro se naopak spouští jenom při „překladu“ šablony. V podstatě to nějaký kód nahradí za jiný pouze jednou. Při renderování šablony se pak už spouští pouze nový kód. Makro nemá vůbec přístup k hodnotám proměnných $foo je pro něj jen část vstupního řetězce.

Snad je to takhle aspoň trochu pochopitelný. Pro případ nějakého zpracování obrázku bych volil helper, protože budu nejspíš potřebovat instanci Image něčím nahradit…

jtousek
Člen | 951
+
0
-

To jo, ale třeba v tomhle případě. Napíšu si funkci, která mi $image převede na Data URI scheme.

A nyní mám dvě možnosti:

{image $image} {* převede se na něco jako <?php echo data_uri_scheme($image); ?> *}

nebo:

{$image|image} {* |image je zaregistrovaný helper který volá stejnou funkci *}

Co z toho mám použít a proč?

//EDIT:

Anebo třetí možnost, dát tu funkci jako metodu Nette\Image (nebo poděděné třídě):

{$image->getDataUriScheme()} {* nebo magicky přes properties *} {$image->dataUriScheme}

Editoval jtousek (2. 3. 2011 10:50)

Tharos
Člen | 1030
+
0
-

Nepovažuji se za zkušenějšího, ale přispěji svým názorem: osobně helper vnímám jako něco, co když se vynechá, tak stále na výstupu zůstanou použitelná data. Například když zapomenu helper formátující datum, na výstupu zůstane datum, jen jinak formátované. A tak dále… No a jelikož zde tedy $image asi nebude obsahovat URL obrázku, osobně bych zde šel cestou vlastního makra.

Dále bych řekl, že makra jsou náročnější na definici (hlavně pak makra s mnoha parametry), ale zato přinášejí podstatně více možností.

Editoval Tharos (2. 3. 2011 10:38)

norbe
Backer | 405
+
0
-

Když nad tím teď přemýšlím, asi by skutečně bylo nejlepší makro, jelikož jinak by se Ti výstup automaticky escapoval (předpokládám že to by asi nedělalo zrovna dobře). A je podle mně lepší ! používat co nejmíň, protože když pak budeš mít člověka, co za tebe bude dělat šablony a jednou mu to bez vykříčníku fungovat bude, podruhý ne, tak ho postupně začne cpát všude…

Filip Procházka
Moderator | 4668
+
0
-

Když nad tím tak přemýšlím! Tak by skutečně bylo lepší udělat si presenter, který bude servírovat obrázek. Ale nejenomže bude servírovat obrázek, ale on ho uloží do nějaké složky a v .htaccess bude pravidlo, které, když bude existovat obrázek, který chci načíst, tak mi ho poskytne z té složky a když nebude existovat soubor tak mě přesměruje na presenter, který ho vytvoří a vrátí. V dalším požadavku už bude soubor existovat a nebude zatěžovat aplikaci, ale bude ho servírovat apache/nginx/… tady bych pokračoval se čtením…

Editoval HosipLan (2. 3. 2011 11:14)

jtousek
Člen | 951
+
0
-

HosipLan: Což je naprosto nepoužitelné, v případě, že ten obrázek nemá být přístupný všem, ale jen uživatelům s dostatečnými právy.

Editoval jtousek (2. 3. 2011 11:26)

Tharos
Člen | 1030
+
0
-

Já myslím, že dost záleží na celém zadání a na požadavcích. Pokud by se například mělo jednat o přístup přihlášeného uživatele k obrázku, za který zaplatí, asi by nebylo ideální, aby se ve výsledku obrázek reálně objevil v document rootu.

Jinak jsem zastáncem myšlenky, že není špatně, když například z výkonnostních důvodů existují v projektu kódy nevyužívající Nette. Já takhle řeším například ajaxová rozhraní, přes která si v pravidelných intervalech tahají data Google mapy. Potřebuji tam jen protlačit jednoduchá JSON data a opravdu nevidím důvod, proč kvůli každému takovému requestu načítat do paměti všechny Nette třídy (minified verze). Proč podobnou jednoduchou „gateway“ pro obrázky řešit přes Nette, respektive jaký je přínos? Kromě určitě „konzistence“ (za cenu obětovaného výkonu).

22
Člen | 1478
+
0
-

situace odpovídá: přístup jen pro přihlášeného uživatele tedy přes URL ten obrázek nemůže být dosažitelný, ale jeho načtení zprostředkuje nějaká metoda. Helper by to asi vyřešil, ale jak by měl vypadat, problém nastane asi s hlavičkama, který jsou odeslaný, tzn. nějaký iframe?

Tharos
Člen | 1030
+
0
-

No, já bych to teda v tomto případě řešil tak, jak píše jtousek. Prostě v presenteru, pokud má uživatel práva k obrázku přistoupit, bych jej předal do šablony (přes nějakou třídu s metodou, která by na vstupu dostala umístění obrázku na serveru a vracela by jeho Data URI tvar). V šabloně můžeš kontrolovat, zda jsou data předána – pokud ne, můžeš například zobrazit nějaký univerzální „not allowed“ obrázek. Vůbec bych se nedělal s helpery či makry.

Edit: Po prozkoumání problémů s Data URI bych od tohoto řešení šel rychle pryč (například nesmyslný 32 KB limit v IE8). :( Takže zde je asi nejvhodnější řešení opravdu speciální presenter pro získávání obrázků, i přes ten výkonnostní overhead. :(

Editoval Tharos (2. 3. 2011 12:13)

David Grudl
Nette Core | 8228
+
+1
-

{$image|dataStream} nefunguje?

22
Člen | 1478
+
0
-

funguje :-) super a diky!

jtousek
Člen | 951
+
0
-

DG: Aha. :-) O tom jsme bohužel nikdo nevěděli. Ale stejně po diskusi, která zde proběhla mi připadá lepší napsat si makro.

Petr Motejlek
Člen | 293
+
0
-

Vydlabte se na nějaké obalování obrázku PHPkem a použijte Apache, případně LightHTTPd modul XSendFile ;).

V PHP si otestujete, jestli ten, kdo obrázek (soubor, cokoliv) chce, ho může chtít. Když ho nemůže chtít, vyhodíte 401, případně 404. Když může, tak nastavíte hlavičku X-SendFile na cestu k souboru a ukončíte PHP. XSendFile modul si sám tu hlavičku kontorluje, a když je nastavená, postará se o odeslání souboru. Běží to úplně mimo PHP, takže je to velmi rychlé a nezdržuje to PHP vlákna.

XSendFile se stará jen o to poslání souboru. Content-Type hlavičku samozřejmě musíte taky nastavit.

Já na to teď používám jednoduchý php soubor, který si natáhne bootstrap, ale nespouští aplikaci. Pouze otestuje, jestli uživatel může, příp. nemůže, a nastavuje hlavičky ;). Velmi jednoduché a rychlé.

Asi někdo namítne, že XSendFile nejspíš bude použitelný jen na vlastním hostingu, ale při dnešních cenách VPS už sdílené hostingy půjdou IMHO stejně brzo do kytek … :)

jtousek
Člen | 951
+
0
-

Petr Motejlek: Promiň ale moc tě nechápu. Otestování zda uživatel ten obrázek může chtít znamená ověřit to PHPkem skrz ACL vrstvu ⇒ potřebuju Nette.

O pár řádek níž zase píšeš, že PHP soubor používáš (jen nespouští aplikaci, jen ci načte co potřebuje). Tak teda potřebuju PHP nebo ne?? Jinak s tím že je to přes PHP soubor jednoduché souhlasím, s tím že je to rychlé těžce nesouhlasím – takových obrázků mohu mít snadno 50 na stránce (neveřejná fotogalerie).

blacksun
Člen | 177
+
0
-

Hmm, XSendFile jsem neznal, už jsem ho nahodil na server a v nejbližší době otestuju.

22
Člen | 1478
+
0
-

Tady ale jde/šlo spíš o zobrazení obrázku, než download a 401/404 je docela nežádoucí chování.

Petr Motejlek
Člen | 293
+
0
-

@jtousek: PHP používám kvůli ověření ACL, atd. Ale díky XSendFile nepotřebuju načítat nic z toho soboru, který posílám, do paměti v rámci PHP. Odeslání si zajistí ve vlastní režii Apache (XSendFile).

Jde mi o to, že nutně není potřeba žádnej DownloadResponse, případně dataStream helper ;).

P. S.: Pokud se dobře dívám, napsal jsem, abyste se vydlabali na obalování obrázku PHPkem. Tím jsem měl na mysli právě ty věcičky jako DownloadResponse, atd.

Petr Motejlek
Člen | 293
+
0
-

22 napsal(a):

Tady ale jde/šlo spíš o zobrazení obrázku, než download a 401/404 je docela nežádoucí chování.

Jak to myslíš? 404/401 přece vyhodím, když někdo zadá špatně id, nebo není např. přihlášen ;).

Jde mi o to, že na to samotné poslání dat z nějakého souboru (ať už je to obrázek, nebo binárka) přece nepotřebuju PHP. PHP potřebuju na ověření, atd.

Na XSendFile se mi líbí, že nemusíš dělat nic jiného, než nastavit hlavičku, a ono si samo ohlídá, jak poslat soubor. Krásně fungujou třeba přerušený stahování a progresivní obráky.

bojovyletoun
Člen | 667
+
0
-

Trochu střelím: ale bude se hodit ImageResponse? Popř ImageHelper? (názvy tříd hledej na foru)

22
Člen | 1478
+
0
-

Petr Motejlek napsal(a):

22 napsal(a):

Tady ale jde/šlo spíš o zobrazení obrázku, než download a 401/404 je docela nežádoucí chování.

Jak to myslíš? 404/401 přece vyhodím, když někdo zadá špatně id, nebo není např. přihlášen ;).

Jde mi o to, že na to samotné poslání dat z nějakého souboru (ať už je to obrázek, nebo binárka) přece nepotřebuju PHP. PHP potřebuju na ověření, atd.

Na XSendFile se mi líbí, že nemusíš dělat nic jiného, než nastavit hlavičku, a ono si samo ohlídá, jak poslat soubor. Krásně fungujou třeba přerušený stahování a progresivní obráky.

Jde o to, že na soubor potřebuju odkazovat:

<img src="{$id}.jpg">

kde link vede do neveřejné složky webu.., což tvoje řešení pak nevyžaduje složku mimo root webu?
nezkoumal jsem ten Apache modul, ale první problém bude, že málokterý hosting to má a zatím drtivá většina webů jede na pronajatém hostingu, nejen kvůli ceně, ale i servisu (zálohování, záložní zdroj a jiné).
Mě zajímá, co se stane v šabloně, když Apache pošle 404? A jak se Apache dozví, když budou fotky na veřejném prostoru a někdo si je vyžádá přes URL, že zrovna tenhle občan nemá oprávnění, když je PHP mimo?

Petr Motejlek
Člen | 293
+
0
-

@22: Čteš vůbec ty moje komentáře celé? V tom prvním jsem jasně napsal, že na sdíleném hostingu nejspíš XSendFile nikdo nemá. Takže ta rada platí jen pro lidi, co mají vlastní VPS, případně server ;) A jen tak mimochodem, dneska ti zálohování atd. nabízí skoro každý dobrý VPS provider.

V dřívějších verzích poslal XSendFile naprosto cokoliv, k čemu jsi mu v hlavičce zadal cestu. Aktuální verze si umí omezit adresář, ze kterého to jde (včetně podadresářů).

Tahle diskuze mě už přestává bavit. Chtěl jsem jen lidem, kterým to trochu myslí, poradit skvělý modul, který řeší všechny problémy fyzického poslání souboru uživateli. Nechci sem kopírovat dokumentaci ani žádný use case. Pokud máš k dispozici nějakou VPS, případně server, nahlédni do dokumentace a zkoušej. ;)

Petr Motejlek
Člen | 293
+
0
-

bojovyletoun napsal(a):

Trochu střelím: ale bude se hodit ImageResponse? Popř ImageHelper? (názvy tříd hledej na foru)

Nevím, jak to myslíš. Ani jedno nepoužívám. V šabloně odkazuju např. na {$id}.jpg. Pak si v .htaccess pohlídám, že [0–9]+.jpg se vnitřně přesměruje na image.php?id=XXX, ten si zkontroluje přístupová práva a nastaví hlavičky (buď 40X, nebo XSendFile).

lvq
Člen | 47
+
0
-

Dovolim si ozivit tema, mam totiz otazku tykajici se primo tohoto tematu.
Zkousel jsem pouzit

{$image|dataStream}

, ale kdyz to napisu do sablony,

<img src="{$fot|dataStream}" alt="">

tak to nefunguje v ie6 ani ie7, v chrome i FF jede dobre.
Dela to jen me, nebo je to nejaky problem, pokud ano, jak jej lze vyresit?
Obrazek vytvorim:

$this->template->fot = NImage::fromFile($cesta);

a pouzivam nette 2 na PHP 5.2
Diky za jakoukoli radu.

bojovyletoun
Člen | 667
+
0
-

Bill Gates řekl:„32 kB bude stačit všem“ – http://caniuse.com/#…
Možná v IE 9 pokročili, tam už to bude fungovat
OT: Tohle je recese?

22
Člen | 1478
+
0
-

OT: IE9 je další povedenej kousek :-) ať žijí rozmazaný weby! ClearType nejde vypnout, ani v registrech se mi to zatím nepodařilo, jediná šance je přepnout se do režimu prohlížení IE8, jestli nechcete přijít o oči.

Editoval 22 (21. 3. 2011 20:32)

Petr Motejlek
Člen | 293
+
0
-

@22, @bojovyletoun: Nechtěl by někdo Hulánovi hacknout bankovní účet? Už delší dobu se domnívám, že mu do něj Microsoft pravidelně hrne nějaký finance ;). Takhle se přeci racionálně smýšlející člověk nechová…