Obrázek – vykreslení v šabloně
- 22
- Člen | 1478
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
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
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
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
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
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
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
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)
- Tharos
- Člen | 1030
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).
- Tharos
- Člen | 1030
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)
- Petr Motejlek
- Člen | 293
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
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).
- Petr Motejlek
- Člen | 293
@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
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
Trochu střelím: ale bude se hodit ImageResponse? Popř ImageHelper? (názvy tříd hledej na foru)
- 22
- Člen | 1478
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
@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
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
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
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?
- Petr Motejlek
- Člen | 293
@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á…