Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: fortran1986 07. 11. 2025, 00:19:45

Název: Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: fortran1986 07. 11. 2025, 00:19:45
Ahojte v mojej web platforme ukladám obrázky do DB. Mám tam aj plnú velkosť obrázka a k tomu dva náhľady v rôznych velkostiach (MD, SM, Full):
Hlavný obrázok je uložený v takom formáte v akom ho nahral užívateľ (v prípade, že ide o webový formát teda webp, jpeg, png, gif, avif ak to neni webový formát napr psd, raw alebo tiff systém si ho skonvertuje do webp a uloží) a k nemu je v tabulke stĺpec contentType aby sme vedeli aký formát obrázok používa.
K databáze som spravil ImageCacheService ktorý tieto obrázky lazy metódou ukladá do filesystemu a keď treba posiela ku klientovi (je to rýchlejšie ako priamo select do db). Ak je v DB novší obrázok ako je dátum obrázka na disku obrázok sa prepíše verziou z DB. názvy obrázkov sú GUIDy tiež z DB tabulky a k nim som pridal extension (podla formátu) nakoľko súbory majú extension http server ich posiela so správnym mime type. Premýšlam ale že tie extensions vypnem. Aby som prípadným zlodejom podľa možnosti skomplikoval sťahovanie obrázkov. Viem že to neni veľká kompikácia (preto tam davam aj vodoznak atd) ale bol by som rád keby moje obrázky vyzerali takto:

Kód: [Vybrat]
<img src="5b17f8185e71449983e3600a0c2d8527">
a nie takto:

Kód: [Vybrat]
<img src="5b17f8185e71449983e3600a0c2d8527.webp">
ide len o to že tie mime types sú v DB a ja som robil cache koli tomu aby som nerobil zbytočne veľa prístupov do DB, keď koncovku vypnem, ako zistím mimeType obrázka? Mám si urobiť nejakú ďalši in-memory cache na mimeTypes? Alebo na to použijem noSQL databázu. Keby išlo o malý web tak to vyriešim nejakým actorom s ConcurrentDictionary. Ale na webe budú možno aj 10tky miliónov obrázkov. Takže potrebujem riešenie ktoré do pamate načíta tie obrázky ktoré sa bežne načítajú a tie ostatné čo sa málo používajú, by mohol postupne čistiť garbage collector. Určite nechcem všetko v pamati.
Název: Re:zobrazenie obrázkov z DB na webe bez koncovky.
Přispěvatel: fortran1986 07. 11. 2025, 00:24:33
AI mi radí použiť k SQL Serveru ešte noSQL

Redis, Memcached, atď

Ale ja neviem je to dobrý nápad? neni to kanón na vrabce? Ono by sa to dalo použiť neskôr aj na iné optimalizácie nie?
Název: Re:zobrazenie obrázkov z DB na webe bez koncovky.
Přispěvatel: BoneFlute 07. 11. 2025, 02:13:23
1/ Ukládat si do filecache včetně koncovky. Pomocí htaccess následně řešíš jen existenci

2/ Ukládat si do filecache bez koncovky, ale s fixním typem. IMHO poněkud vachrlaté. A u toho originálu se ti to asi nebude chtít.

3/ Ukládat si do filecache bez koncovky, a hned vedle ukládat soubor s mime. Něco jako "5b17f8185e71449983e3600a0c2d8527" = obsah. "5b17f8185e71449983e3600a0c2d8527.mime" a v něm obsah "image/png". Pokud se dotazuješ na soubor bez koncovky tak stejně budeš muset posílat nějak hlavičku, takže nějaká mikro-proxy tam bude potřeba. Pomocí čistě htaccess by to asi nešlo. Možná nějaké pravidlo na serveru, záleží.
Název: Re:zobrazenie obrázkov z DB na webe bez koncovky.
Přispěvatel: Kit 07. 11. 2025, 02:25:06
Tu koncovku bych tam určitě nechal. Nebudeš muset manipulovat s hlavičkami HTTP.

Do databáze bych uložil jen názvy a náhledy. Originály obrázků do souborového systému. Vyzkoušeno.
Název: Re:zobrazenie obrázkov z DB na webe bez koncovky.
Přispěvatel: Filip Jirsák (forum) 07. 11. 2025, 08:35:57
Za prvé bych soubory neukládal do relační databáze, zejména když je pak stejně máte uložené ještě jednou na disku. Pokud ty obrázky nemáte ve více formátech (jeden obrázek), nechal bych v odkazech ty přípony – ničemu tam nepřekáží. Tvrzení, že byste tím zlodějům zkomplikoval stahování obrázků, je nesmysl. Na disku pak ty soubory také uložte s příponou a máte po problémech.

Pokud byste opravdu trval na tom, že soubory budou na disku uložené bez přípony, uložte jejich typ do rozšířených atributů. Pro uložení MIME typu dokumentu je určen atribut user.mime_type – některý web server pravděpodobně půjde nakonfigurovat tak, aby MIME typ z tohoto rozšířeného atributu načítal.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: speculatius 07. 11. 2025, 19:36:38
Ak som správne pochopil, tak tie obrázky sa posielajú skrze ImageCacheService. Teda cez nejaký endpoint v tvojej aplikácii, ktorý pri dopyte načíta obrázok z disku a odošle ho. A pravdepodobne to beží v nejakom interpretovanom jazyku ako PHP, Ruby, Python alebo tak...

Moja skúsenosť je taká, že tento prístup je veľmi pomalý a nebude zvládať obsluhovať ani menší počet klientov. O niekoľko rádov rýchlejšie je ukladať obrázky do public adresára a zvyšok nechať na webserver (Apache?). Ten nie je interpretovaný a je na tento use-case optimalizovaný.

V taktom prípade by bolo najjednoduchšie ponechať koncovky a webserver sa o všetko postará.

Druhou možnosťou je odstrániť koncovky a podsunúť webserveru správny mime-type. Napr. Apache má niečo ako direktívu ForceType. Teda rôzne typy obrázkov by som ukladal do rôznych podadresárov a tým nastavil príslušný ForceType.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: BoneFlute 07. 11. 2025, 21:24:26
Teda rôzne typy obrázkov by som ukladal do rôznych podadresárov a tým nastavil príslušný ForceType.
Na první pohled to vypadá jako super nápad. Ale když se nad tím zamyslím, jak budete z "/imgs/5b17f8185e71449983e3600a0c2d8527" rozlišovat do jakého podadresáře se má dotazovat?
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: Zopper 08. 11. 2025, 08:11:48
Premýšlam ale že tie extensions vypnem. Aby som prípadným zlodejom podľa možnosti skomplikoval sťahovanie obrázkov
To nedává smysl. :o

Jakému stahováním to přesně má bránit? Pokud to je prohlížeč schopný zobrazit, tak musí vědět, co je to za typ. A cokoliv bude ty obrázky stahovat, ať už addon v prohlížeči, curl, python..., tak má úplně stejné možnosti. Vlastně ještě větší, protože když na to přijde a budu ti ty obrázky chtít ukrást, tak si je prostě postahuju, a pak na ně pustím file, co ten typ uhodne podle magických čísel a struktury, a tím pádem si to zobrazím, i pokud prohlížeč bude v koncích.
Kód: [Vybrat]
$ file /tmp/foo
/tmp/foo: PNG image data, 1236 x 614, 8-bit/color RGBA, non-interlaced

A proti stahování náhodným zkoušením všech možných filenames stačí ten hash-like name - procházet všechny permutace je prakticky nereálné. A mimochodem, zkrátit ho o tři znaky naopak situaci zjednodušuje (stačí mi zkusit jenom 5b17f8185e71449983e3600a0c2d8527 místo 5b17f8185e71449983e3600a0c2d8527.jpg, 5b17f8185e71449983e3600a0c2d8527.jpeg, 5b17f8185e71449983e3600a0c2d8527.png, ...)

Když příponu necháš, tak, jak už tu zaznělo, to můžeš nechat servírovat Apachem nebo Nginxem a bude to mnohem rychlejší a jednodušší.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: speculatius 08. 11. 2025, 11:07:35
Teda rôzne typy obrázkov by som ukladal do rôznych podadresárov a tým nastavil príslušný ForceType.
Na první pohled to vypadá jako super nápad. Ale když se nad tím zamyslím, jak budete z "/imgs/5b17f8185e71449983e3600a0c2d8527" rozlišovat do jakého podadresáře se má dotazovat?

Boli by tam adresáre ako images/jpeg, images/png atď. Logika kontrolera je potom asi takáto...


Tento prístup s 302 sa môže zdať ako okľuka, ale umožňuje práve updatovanie zmenených obrázkov, kontrolu prístupových práv a tak podobne. V prípade potreby by sa to dalo vyriešiť aj bez neho, keď by sa obrázky updatovali napr. vždy v noci.

Otázkou samozrejme ostáva, či to má nejaký zmysel. Používateľ si môže obrázok stále stiahnuť, len ten súbor nebude mať koncovku. Technicky zdatnejšieho používateľa to nezastaví. A pre najjednoduchších používateľov je asi lepšie zakázať right click alebo dať pred obrázok priesvitný div.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: BoneFlute 08. 11. 2025, 16:22:10
Teda rôzne typy obrázkov by som ukladal do rôznych podadresárov a tým nastavil príslušný ForceType.
Na první pohled to vypadá jako super nápad. Ale když se nad tím zamyslím, jak budete z "/imgs/5b17f8185e71449983e3600a0c2d8527" rozlišovat do jakého podadresáře se má dotazovat?

Boli by tam adresáre ako images/jpeg, images/png atď. Logika kontrolera je potom asi takáto...

  • Príde dopyt na ImageCacheService, napr. na https://.../cache-service/123
  • ImageCacheService urobí rýchly select do DB, aby zistil správy mime-type, timestamp a vyskladal cestu ako https://.../public/images/jpeg/123. Selectu sa teda nevyhneme, ale je podstatne rýchlejší ako ťahať z databázy celé raw dáta.
  • Ak je to potrebné, príslušný obrázok na disku v adresáry /var/www/public/images/jpeg/123 sa vytvorí, prípade updatne.
  • Kontroler odpovie pomocou 302 Moved Temporarily https://.../public/images/jpeg/123
  • Browser načíta daný obrázok, ktorý Apache odošle so správnym mime type.

Tento prístup s 302 sa môže zdať ako okľuka, ale umožňuje práve updatovanie zmenených obrázkov, kontrolu prístupových práv a tak podobne. V prípade potreby by sa to dalo vyriešiť aj bez neho, keď by sa obrázky updatovali napr. vždy v noci.

Rozumím. V tom případě to je spíše horší než lepší nápad. Protože se bavíme o cache, a o tom jak to udělat co nejlevněji. A toto, pokud mě něco podstatného neuniklo, je stále dražší než se prostě jen ptát na existenci souboru a maximálně si vytáhnout info o mime ze sousedního souboru nebo z xattr.

V každém případě dík za info. Ve skutečnosti jsem ForceType neznal.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: Kit 08. 11. 2025, 18:11:26
Rozumím. V tom případě to je spíše horší než lepší nápad. Protože se bavíme o cache, a o tom jak to udělat co nejlevněji. A toto, pokud mě něco podstatného neuniklo, je stále dražší než se prostě jen ptát na existenci souboru a maximálně si vytáhnout info o mime ze sousedního souboru nebo z xattr.

V každém případě dík za info. Ve skutečnosti jsem ForceType neznal.

Pokud by nevymýšlel blbosti, nechal přípony a všechny obrázky uložil do souborového systému, tak nemusí řešit ani cache.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: MalyTomi 08. 11. 2025, 18:40:06
zbytocne komplikacie, kedze aj tak vysledok bude nejaky obrazok, ktory sa zobrazi. a co sa zobrazi, to sa da ulozit.
Preco si do db neukladat proste zakladne info o obrazku a samotne obrazky ukladat na disk, napr. pod nejakym hash nazvom. Skript si proste urobi jednoduchy select podla toho hash, z db vytiahne potrebne info a posle to klientovi aj so spravnymi hlavickami. Funguje to tak roky.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: BoneFlute 08. 11. 2025, 19:57:16
Preco si do db neukladat proste zakladne info o obrazku a samotne obrazky ukladat na disk, napr. pod nejakym hash nazvom. Skript si proste urobi jednoduchy select podla toho hash, z db vytiahne potrebne info a posle to klientovi aj so spravnymi hlavickami. Funguje to tak roky.

Drahý.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: Zopper 09. 11. 2025, 07:33:43
Ano, ale... relativně drahé. Obsloužit dotaz čistě na základě souborů sice bude několikanásobně rychlejší, než cesta do databáze a zpátky (i když o kolik přesně, to extrémně záleží na technologiích a kde jsou fyzicky servery). Ale zároveň to může být honění si milisekund. Pokud trvá 500 ms, než se to návštěvníkovi načte v prohlížeči, z toho 1 ms je práce webserveru a 10 ms je navíc ten databázový dotaz, a ten webserver se vlastně pořád tak trochu fláká, protože dělá 5 zobrazení za sekundu, změní těch 10 ms něco? Ta cesta do DB se aspoň může použít na něco jako "zobraz obrázky jen přihlášeným uživatelům," pokud je to potřeba.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: Filip Jirsák (forum) 09. 11. 2025, 10:14:24
Je to drahé na vývoj i na provoz. Na vývoj, protože se tam musí implementovat logika ukládání do databáze, pak cachování v souborovém systému, asi promazávání cache v souborovém systému. Na provoz pak nejen samotné vystavení souboru uživateli, ale třeba i zálohování. Databázi musíte zálohovat celou (i když třeba zálohujete i přírůstky, chcete mít ne moc starou kompletní zálohu - abyste v případě obnovy neobnovoval přírůstky za 5 let). Když jsou soubory uložené v souborovém systému, stačí zálohovat jen nové soubory, na staré zálohy nemusíte sahat.

Přihlášeného uživatele asi dokážete poznat z hlaviček požadavku, na to nepotřebujete lézt do DB. To by bylo potřeba jen v případě, kdy by bylo potřeba ověřovat práva uživatele ke konkrétnímu souboru. O čemž za prvé nebylo nic psáno, za druhé by stejně bylo jednodušší to udělat v okamžiku generování odkazů na ty obrázky.
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: RDa 09. 11. 2025, 14:52:41
Taky muzes rezervovat nejaky cislo (prvni, posledni) z toho hashe pro typ souboru. A pak pres mod_rewrite tomu overridnout mime type podle regexu z url.

Cachovani ma smysl, pokud cesta z cache je nejrychlejsi - tj. nativni stahovani skrze httpd, zadne cgi, skripty, a uz vubec ne databaze!

Cache miss muzes resit pres mod_rewrite, resp. 404 handler implementovat skriptem, ktery pregeneruje soubor a forcne reload (treba Location .?time=$now$hash), ale potrebujes to udelat trocha chytreji, at ti to nekdo nevyDDoSuje, tim ze se hromada klientu bude snazit nacist to same.. tj potrebujes mutex.

Jako celkove na to jdes spatne.. vytvoris si velky problem a pak se ho snazis vyresit dalsim hnojem :D

Co si trocha popremyslet nad architekturou, nez zacnes neco vytvaret a implementovat?
Název: Re:Zobrazenie obrázkov z DB na webe bez koncovky
Přispěvatel: Michal Šmucr 09. 11. 2025, 15:27:30
Těch možností je víc, jak už to zaznělo. Ale za mě, pokud tam není nějaká vstupní konverze obrázků na jednotný formát (což může mít také své výhody, byť by se třeba vstupní soubor někam zálohoval) a měl tam v jednom adresáři mix formátů, asi bych se nezdráhal jít tím nejjednodušším způsobem a nechal tam přípony.

Jinak, vím že jste se na to neptal a už to máte hotové ;), ale taky bych tak nějak spíš inklinoval k tomu, neukládat všechny obrázky jako BLOBy do databáze a servírovat je klientům přes tuhle lazy cache.
Chápu, že to někdy může mít své výhody a samozřejmě nevím, co je to za systém, ale pokud db začne velikostně bobtnat, může to přinést řadu praktických problémů. Takže pokud bych tam už něco měl ukládat, tak né originální uploady, ale pokud to bude dávat výkonostně smysl, tak třeba jen ty malé náhledy, kde se dá dobrat k někjaké predikovatelné velikosti a všechno bude mít jeden formát.
Ukládání souborů samotných pak dělat do podadresářů podle prvních znaků hashe, třeba jako Git. Mezi nimi se to bude víceméně automaticky dělit a na filesystému nevzniknou hotspoty, ani když tam bude opravdu hodně souborů a bude k tomu přistupovat víc procesů/vláken.
U toho pojmenování to pak jde samozřejmě udělat tak, jak to máte - podle nějakého GUIDu z databáze, nebo se to dá udělat také podle hashe z obsahu souboru. Což může mít výhodu v tom, že pokud tam budou ukládat data uživatelé, můžu to rovnou deduplikovat, když tam budou opakovaně sypat ty samé soubory.. V db pak dvě tabulky - např. pro obrázky (s těmi guidy, metadaty, origo názvem) a pak pro soubory (na disku), mezi kterými je vazba.
Celé tohle pak poskytuje vcelku široké možnosti, jako to v provozu optimalizovat, když bude potřeba. Statické soubory můžou být na jiném hostu než databáze, v extrému i ty jednotlivé podadresáře. Ukládat můžu jak do disku, případně to pak to i po nějaké době s relativně minimálními úpravami přesunout třeba do nějaké S3 storage (kde ty původní podadresáře budou jen prefixy).
Pokud bude potřeba další cachování, můžu to dělat klasicky přes reverzní proxy někde na edge serverech.. což jde samozřejěmě i s tou lazy cache, ale je to db -> lazy cache -> druhá cache.. A pokud to třeba nahodím na jiném stroji bez cache, a přesměruju tam provoz, tak tam budu mít na úvod poměrně velké vytížení db, než se ta lazy cache naplní.
Asi i proto bych měl tendenci se spíš držet té klasické architektury.