Autor | Zpráva | ||
---|---|---|---|
xtas Profil |
#1 · Zasláno: 13. 2. 2013, 11:18:16
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 |
#3 · Zasláno: 13. 2. 2013, 12:43:16
xtas:
Nemáte tam automaticky nastavený nějaký výstupní filtr (např. deflate)? |
||
xtas Profil |
#4 · Zasláno: 13. 2. 2013, 12:46:49
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 |
#5 · Zasláno: 13. 2. 2013, 12:54:26
xtas:
V komentářích v manuálu ještě uvádí variantu s fopen místo readfile. |
||
xtas Profil |
#6 · Zasláno: 13. 2. 2013, 12:58:10 · Upravil/a: xtas
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 |
#7 · Zasláno: 13. 2. 2013, 13:10:40
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 |
#8 · Zasláno: 13. 2. 2013, 13:22:51
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 |
#12 · Zasláno: 14. 2. 2013, 18:42:43
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 |
#13 · Zasláno: 14. 2. 2013, 19:18:07
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 |
#15 · Zasláno: 15. 2. 2013, 12:55:02
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 |
#16 · Zasláno: 15. 2. 2013, 16:36:38
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 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 |
#17 · Zasláno: 15. 2. 2013, 19:50:57
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 |
#18 · Zasláno: 16. 2. 2013, 10:33:29
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 |
#19 · Zasláno: 16. 2. 2013, 11:20:28
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 |
#20 · Zasláno: 18. 2. 2013, 11:24:59 · Upravil/a: xtas
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 |
||
Časová prodleva: 11 let
|
0