ugrás a tartalomhoz

Nagy fájlok kiszolgálása PHP-vel

mahoo · 2012. Jún. 28. (Cs), 18.17
Jelenleg egy 56M-ás fájlt szeretnék letöltésre kiszolgálni, de a "Fájl nem található" üzenetet kapom a böngészőtől.

Amit eddig próbáltam: http://php.net/manual/en/function.readfile.php#48683
Illetve a memória limit 128M-án van.

A 3xM-os fájlt vagy kisebbel nincs gond.

Merre induljak, milyen beállítással lehet esetleg gond?
 
1

Megoldás

Hidvégi Gábor · 2012. Jún. 28. (Cs), 19.15
Olyan parancsot használj a fájl beolvasására, ami nem az egészet veszi, hanem darabokban végzi el egy pointer segítségével. Közben ideiglenesen altathatod a script futását, így gyakorlatilag szabályozod a letöltési sebességet.
2

Szerintem a php.net-es példa

mahoo · 2012. Jún. 28. (Cs), 22.20
Szerintem a php.net-es példa is darabokban olvassa be a fájlt, vagy másfajta megoldásra gondolsz. Bár az tény, hogy altatás nincs benne.
3

Nem jó

janoszen · 2012. Jún. 28. (Cs), 22.27
Alapvetően a statikus fájlok kiszolgálása PHP-val nagyon rossz ötlet, mert agyonvered az operációs rendszer saját cache-selését. Ha már muszáj a letöltést lassítanod, akkor ezt inkább az operációs rendszer szintjén oldd meg.

Ezt elmondva az a megoldás, hogy darabonként olvasol és nyomod ki a böngészőnek a tartalmat, tehát valahogy így:

if (($fp = fopen('nagyfile.bin', 'rb')) !== false) {
    while (!feof($fp)) {
        echo(fread($fp, 4096));
        flush();
    }
    fclose($fp);
}
Természetesen arra figyelni kell, hogy ha az output buffering aktív, akkor előbb abból ki kell lépni, különben a PHP gyűjtögeti memóriában a tartalmat:

while (ob_get_level()) {
    ob_end_flush();
}
4

Sajnos, sehogy sem megy...

mahoo · 2012. Jún. 29. (P), 06.47
Sajnos, sehogy sem megy... egyelőre... kutatok tovább.
5

Debug

janoszen · 2012. Jún. 29. (P), 09.18
Akkor allj neki debuggolni. xdebuggal tudod nezni, hogy mit csinal a PHP, hol szall el. Wiresharkkal tudod nezni a halozati forgalmat. A hibalogban pedig megtalalod, ha volt valami kohoges. Kulonosen ha az error_reporting opcioban bekapcsolod a notice-okat.

Egyebkent egy kitakaritott valtozatot felmasolhatnal valahova, had nezzem meg. Nem letezik, hogy ez ne mukodjon.

Egyebkent mi az uzleti motivacio emogott a megoldas mogott? Ha elmondod, lehet hogy tudok sokkal jobb megoldast mondani, mert ez igy elegge hackeles szagu.
6

Darabokban

joed · 2012. Jún. 29. (P), 15.30
Darabokban told ki kliensnek a fájlt, ha már nagyon PHP-ban kell megoldanod.

Pl.:


[...]

const CHUNK_SIZE = 1024;

/**
 * @param $filename string Path to file that is going to be sent
 */
public static function readfile_chunked($filename) {
	global $sentCounter;
	$buffer = '';
	$handle = fopen($filename, 'rb');
	if ($handle === false) {
		throw new Exception("Unknown file.");
	}
	while (!feof($handle)) {
		$buffer = fread($handle, self::CHUNK_SIZE);
		echo $buffer;		
		$sentCounter += strlen($buffer);
		ob_flush();
	}	
	fclose($handle);
}

[...]

$fd = {Fájl részletei};

set_time_limit(0);
ob_clean();
header('Content-Description: File Transfer');
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: {$fd->mimetype}");
header("Content-Disposition: attachment; filename=\"{$fd->filename}\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . $fd->size);
{OSZTALYOD}::readfile_chunked($fd->path);
ob_end_flush();
exit;
De ahogy Janoszenszej is mondta, nem tanácsos ilyen feladattal szívatni a szervert, inkább bízd valamilyen célszoftverre, mint pl. a Zend Download Server.
7

Nem voltam időm ma

mahoo · 2012. Jún. 29. (P), 22.40
Nem voltam időm ma próbálkozni csak most, és ezzel a kódrészlettel megy :) köszönöm joed!

De ami a legjobb, hogy most megint megpróbáltam janoszen I proclub példájával és azzal is megy... igen én voltam béna, a file pointer-t nem (jól) állítottam be. Szóval neked is nagyon köszönöm a segítséget janoszen I proclub és elnézést, hogy a bénaságommal félrevezettelek!

Egyébként én erősen a kezdő kategóriába tartozom, és semmiféle hack-elési szándék nincs a feladat mögött csak nem voltam tisztában azzal, hogy az ilyen típusú feladatot más módszerrel illik megoldani.

Szóval nagyon hasznosak voltak a tanácsok!!!