Zobrazenie obrázkov z DB na webe bez koncovky

Zobrazenie obrázkov z DB na webe bez koncovky
« kdy: 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.


Re:zobrazenie obrázkov z DB na webe bez koncovky.
« Odpověď #1 kdy: 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?

BoneFlute

  • *****
  • 2 090
    • Zobrazit profil
Re:zobrazenie obrázkov z DB na webe bez koncovky.
« Odpověď #2 kdy: 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ží.

Kit

  • *****
  • 930
    • Zobrazit profil
    • E-mail
Re:zobrazenie obrázkov z DB na webe bez koncovky.
« Odpověď #3 kdy: 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.

Re:zobrazenie obrázkov z DB na webe bez koncovky.
« Odpověď #4 kdy: 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.


Re:Zobrazenie obrázkov z DB na webe bez koncovky
« Odpověď #5 kdy: 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.

BoneFlute

  • *****
  • 2 090
    • Zobrazit profil
Re:Zobrazenie obrázkov z DB na webe bez koncovky
« Odpověď #6 kdy: 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?

Zopper

  • *****
  • 952
    • Zobrazit profil
Re:Zobrazenie obrázkov z DB na webe bez koncovky
« Odpověď #7 kdy: Dnes v 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šší.

Re:Zobrazenie obrázkov z DB na webe bez koncovky
« Odpověď #8 kdy: Dnes v 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...

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

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.

BoneFlute

  • *****
  • 2 090
    • Zobrazit profil
Re:Zobrazenie obrázkov z DB na webe bez koncovky
« Odpověď #9 kdy: Dnes v 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.