T-Bird Posted May 13, 2009 Share Posted May 13, 2009 I have files that need to be downloaded only if the user has the correct password, thus I'm using the standard readfile() based download method as seen in example 1 of php.net's readfile manual. if (file_exists($file)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename='.basename($file)); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); ob_clean(); flush(); readfile($file); exit; } The files I'm trying to transfer are on average 80MB zip files stored on the same box that is running the scripts. I have two problems which I think are related... but may not be. a) The user submits the password and it takes approximately a minute for the save dialogue box to appear. PHP logs a timeout error, but the file downloads fine. b) With files less than 60MB I can download several files at a time no sweat. With files over 60MB in size I can only download one file at a time. Anyone who tries to download the file while a transfer is in progress gets an empty placeholder file. I tried switching to a chunked transfer method. I got a code out of the comments on the php.net site that seemed promising and tried it. function readfile_chunked($filename,$retbytes=true) { $chunksize = 1*(1024*1024); // how many bytes per chunk $buffer = ''; $cnt =0; // $handle = fopen($filename, 'rb'); $handle = fopen($filename, 'rb'); if ($handle === false) { return false; } while (!feof($handle)) { $buffer = fread($handle, $chunksize); echo $buffer; ob_flush(); flush(); if ($retbytes) { $cnt += strlen($buffer); } } $status = fclose($handle); if ($retbytes && $status) { return $cnt; // return num. bytes delivered like readfile() does. } return $status; } This solved problem-a as data immediately started to transfer to the browser. I didn't get to test if it solved problem-b because after aprox 25-30 seconds php again (understandably) logged the timeout error and the transfer died. Any clue why php is refusing to allow multiple downloads on code a? Is there a way I can adjust PHP's timeout for only ONE page so that I can use code B without having all my pages use an ugly 1hour timeout? Any other suggestions? Quote Link to comment Share on other sites More sharing options...
MadTechie Posted May 13, 2009 Share Posted May 13, 2009 void set_time_limit ( int $seconds ) seconds The maximum execution time, in seconds. If set to zero, no time limit is imposed. so just add set_time_limit(0); to code B Quote Link to comment Share on other sites More sharing options...
T-Bird Posted May 13, 2009 Author Share Posted May 13, 2009 Awesome. Worked great. I feel a little dense though. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.