Autor Zpráva
xtas
Profil
Zdravim,

mam nasledujici problem: na hostingu potrebuju nechat uzivatele stahnout soubor vetsi nez 2GB - cca 2.5GB, ale po autorizaci pres php. Vzhledem k 32-bit prostredi nejdou pouzit funkce fopen,filesize,readfile apod - pise to "failed to open stream: Value too large for defined data type".

Je zapnuty safe_mod, zkousel jsem i variantu exec('cat file.zip') ale zkonci to s chybou 127.

Koukal jsem na mod_xsendfile ktery se mi hodne libi, zatim zjistuju jestli ho na hostingu budou umet nahodit.

Nicmene - je ted nejaky inteligentni zpusob jak soubor dat ke stazeni po autorizaci v php skriptu, tedy pres php - idealne to pak nejak prehodit na apache, protoze php na tohle moc dobry reseni neni, zejmena u velkyho souboru. Soubory jsou ve slozce /files, kam je pres .htaccess zakazany pristup, takze primo linkovat to nejde a ani nema jit.

diky za napady
ShiraNai7
Profil
xtas:
Nicmene - je ted nejaky inteligentni zpusob jak soubor dat ke stazeni po autorizaci v php skriptu, tedy pres php - idealne to pak nejak prehodit na apache, protoze php na tohle moc dobry reseni neni, zejmena u velkyho souboru. Soubory jsou ve slozce /files, kam je pres .htaccess zakazany pristup, takze primo linkovat to nejde a ani nema jit.

Třeba po autorizaci vytvořit symlink() na daný soubor v nějaké dostupné lokalitě, s unikátním názvem (nějaký hash) a pravidelně mazat staré symlinky v rámci CRONu.
Kajman
Profil
xtas:
Nemáte tam automaticky nastavený nějaký výstupní filtr (např. deflate)?
xtas
Profil
ShiraNai7:

jo, to vypada presne jako pouzitelny workaround. Ale pokud to pojmenuju tim hashem a odkazu na nej prohlizec, ten soubor se ulozi
jako nazev toho hashe - je tohle nejak resitelny u varianty se symlinkem?
Kajman
Profil
xtas:
V komentářích v manuálu ještě uvádí variantu s fopen místo readfile.
xtas
Profil
Kajman:
Nemáte tam automaticky nastavený nějaký výstupní filtr (např. deflate)?
myslim ze ne, zkousel jsem to vypnout v htaccess pomoci

<FilesMatch \.avi$>
    SetEnv no-gzip 1
</FilesMatch>

a bylo to stejne - za predpokladu ze toje spravne.


Kajman:
V komentářích v manuálu ještě uvádí variantu s fopen místo readfile.

fopen, filesize, readfile... to je porad stejny problem, neni tam podpora pro velke soubory takze to zkonci hlaskou

failed to open stream: Value too large for defined data type

pokud je soubor vetsi nez 2^31 tedy 2GB.
Alphard
Profil
xtas:
Koukal jsem na mod_xsendfile ktery se mi hodne libi, zatim zjistuju jestli ho na hostingu budou umet nahodit.
O to bych se asi pokusil nejdřív. Nějaku dobu jsem si s tím hrál a fungovalo to myslím dobře. Před třemi lety jsem sem dával i jednoduchou ukázku Download podmíněný zobrazením reklamy.
xtas
Profil
Alphard:
tak mod_xsendfile je bohuzel pase, savana neumi ani neplanuje. skoda - vypadalo to hodne dobre.
ShiraNai7
Profil
xtas:
jako nazev toho hashe - je tohle nejak resitelny u varianty se symlinkem?

Pomocí .htaccess voodoo ano :) Můžeš symlinky pojmenovat ve tvaru hash_název a pomocí .htaccess ten hash uříznout.

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/_/test/download/([a-z0-9]+)_(.+)$ [NC]
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* - [L,E=DOWNLOAD:%2]
Header set Content-Disposition "attachment; filename=%{DOWNLOAD}e" env=DOWNLOAD
xtas
Profil
ShiraNai7:

tak dekuji preuctive. Sice to byl neskutecnej boj s .htaccess a par dalsima drobnostma, ale nakonec sem to zda se dochytal.

Zjistil jsem jeste jednu prasarnu - jakmile necham soubor stahovat, ten symlink muzu smazat a stahovani dal jede klidne hodinu
nez se dostahne celej soubor - je to moc velka prasarna to takhle apachi smazat pod rukama? Ten symlink je jenom odkaz
a i to funguje, ale neni tam nejaky potencialni problem?
ShiraNai7
Profil
xtas:

To netuším. Třeba s obnovou stahování (kdyby ji server podporoval) by mohl být problém, ale interně si to apache zřejmě převede na skutečnou cestu a se symlinkem již nepracuje.
Majkl578
Profil
Myslím, že by neměl být problém posílat velký soubor skrz PHP, pakliže nebude použito bufferování výstupu a soubor bude čten a posílán postupně. Takto to dělá například Nette Framework při posílání souboru klientovi, viz část kódu FileResponse.
ShiraNai7
Profil
Majkl578:
To není až takový problém. Jde především o timeout (xtas zmínil, že používá webhosting) - u velkých souborů anebo pomalých připojení určitě nebude stačit limit (obrovský soubor můžu stahovat i několik hodin). Plus je to o to větší zátěž pro hosting. Řešení přes symlinky tento problém eliminuje.
Majkl578
Profil
ShiraNai7:
Řešení přes symlinky tento problém eliminuje.
A tím problémem myslíš zátěž? Jestli se využije i PHP už podle mě není až takový rozdíl, pokud se použije správně, nicméně testy jsem nedělal.
Nic to ale nemění na tom, že ze serveru je (až několik hodin) aktivní spojení ke klientovi. Jediný rozdíl je, kdo ho obslouží, jestli HTTP server samotný nebo až PHP. S časovým limitem by asi takový problém nebyl, slušné hostingy ho dovolují změnit. Prvně bych si ale ověřil, zda hosting neomezuje počet aktivních spojení. Některé omezují třeba na 20 simultánních spojení, což by znamenalo, že pokud by 20 klientů stahovalo velké soubory, nikdo jiný by si web nezobrazil.
ShiraNai7
Profil
Majkl578:
S časovým limitem by asi takový problém nebyl, slušné hostingy ho dovolují změnit.

Na hostingu, kde xtas psal, že je, mají maximálně 30 minut.

Některé omezují třeba na 20 simultánních spojení

S tím jsem se setkal, ale týkalo se to většinou databáze. Kdyby chtěl provozovat větší "stahovací služby", tak by musel sáhnout po něčem lepším než je sdílený webhosting :)
xtas
Profil
Majkl578:
Myslím, že by neměl být problém posílat velký soubor skrz PHP, pakliže nebude použito bufferování výstupu a soubor bude čten a posílán postupně. Takto to dělá například Nette Framework při posílání souboru klientovi, viz část kódu FileResponse.

z ruznych duvodu bych se rad vyhnul variante aby tam cely soubor tlacilo php, myslim ze apache je na to daleko vhodnejsi a poradi si s tim lepe.

nicmene - to porad za predpokladu ze by to slo, ale ono to nejde. Na 32-bit systemu vraci vetsina souboru pocet prectenych bytu, velikost, pozici v souboru atd jako signed int, a tedy u souboru vetsiho nez 2GB (2^31) to skonci 2 moznyma hlaskama:

[function.readfile]: failed to open stream: File too large
nebo
failed to open stream: Value too large for defined data type

vzhledem k omezeni int se to tyka vsech pouzitelnych funkci jako fopen, fpassthru, filesize..... mozny funkcni reseni by asi bylo neco ve stylu exec('cat file.xx') ale ten apache mi porad prijde podstatne vhodnejsi
Davex
Profil
xtas:
ale ten apache mi porad prijde podstatne vhodnejsi
A potřebuješ k něčemu Apache? Pokud vím, tak na Savaně by se mělo dát přepnout na Nginx (neumí používat .htaccess) a tam by se dala místo X-Sendfile použít hlavička X-Accel-Redirect.
Amunak
Profil
readfile() nejde použít proč? Jestli chápu tu poznámku v dokumentaci dobře, tak tam na to limity nejsou. Ale možná se mýlím.

readfile() will not present any memory issues, even when sending large files, on its own. If you encounter an out of memory error ensure that output buffering is off with ob_get_level().
Davex
Profil
Amunak:
Problém je v tom, že xtasem použitá verze PHP je 32 bitová bez zakompilované podpory velkých (> 2 GB) souborů, jak prozradil jinde.
xtas
Profil
Amunak:
je to jak pise Davex, problem je tohle:

int readfile ( string $filename [, bool $use_include_path = false [, resource $context ]] )

Return Values
Returns the number of bytes read from the file. If an error occurs, FALSE is returned and unless the function was called as @ readfile(), an error message is printed.


v momente kdy v 32-bit php je int 4 bytovej a jeste k tomu signed, max hodnota co je to schopny korektne vratit (tedy pocet prectenych bytu) je 2^31, tedy techj 2.147 GB

Udajne by to melo jit zkompilovat s flagem na podporu velkych souboru - uprimne nevim co to meni, jestli to vraci napr. kB misto B, nebo je jinej datovej typ, nebo to nevraci vubec precteny byty.. s tim nemam zkusenost a pouzit to pro me bohuzel nejde. Nejlepsi reseni je samozrejme 64-bit prostredi, pak se nemusi resit takovyhle blbosti..


Davex:

to sice zni dobre, na nginx jsem kdysi koukal a hodne se mi libil, problem ale je ze tam uz je nekolik projektu ktery pouzivaj htaccess takze by to v tom spis udelalo peknej gulas.

ale mam tam nejaky body ktery v pohode daj na celej dalsi hosting tak to na nem vyzkousim to me docela zajima

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: