Page 1 of 1

[SOLVED] stream length problem

Posted: Sun Aug 08, 2004 3:49 pm
by mlynn
Hi,

I am trying to write a PHP script to do some work before a user can download a file. The URL on my test web page points to my .php script. It will pass a numeric ID to the script I will translate it to a file name on the server but for testing I have hard coded the file name. The problem is that the streaming of the file stops after 251834 bytes.

I am using PHP 4.3.8 and BadBlue Web Server 2.5 on Windows 98.
The server we will eventually use runs Apache version 1.3.31 (Unix), PHP 4.3.8 on Linux but I am just trying out different ways to do this at the moment.

Here is my script:

Code: Select all

<?php
// Download a file using fpassthru()
$fileDir = "images"; // supply a path name.
$fileName = "test.mp3"; // supply a file name.
$fileString=$fileDir.'/'.$fileName; // combine the path and file

// translate file name properly for Internet Explorer.
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")){
  $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1);
}

// make sure the file exists before sending headers
if(!$fdl=@fopen($fileString,'rb'))
{
   die("Cannot Open File!");	// display file id, not file name
}
else
{
	$flen=filesize($fileString);
	header("Content-Type: binary\n");
	header("Accept-Ranges: bytes\n");
	header("Content-Disposition: attachment; filename=".basename($fileString)."\n");
	header("Content-length: " . $flen . "\n");

	rewind($fdl);
	$buffsize=128000;
	$nb=floor($flen/$buffsize);
	$rem=$flen%$buffsize;

	for($n=0;$n<$nb;$n++)
	{
		$contents = fread($fdl, $buffsize);
		echo $contents;
	}
	if($rem!=0)
	{
		$contents = fread($fdl, $rem);
		echo $contents;
	}
	fclose($fdl);
  //fpassthru($fdl);
}
?>
This is the usual "force download" script with a few alterations. I am reading the file in 128k chunks because I am worried about the amount of memory fpassthru would use for large files.

PHP.EXE appears to hang using 0 processor time according to SysInternals Process Explorer. When I kill the PHP.EXE process the Save Dialog appears on the client browser and it saves the first 251834 bytes of the file. Using simple fpassthru($fdl); causes the same problem. If I do not echo the file the file read is OK and takes a fraction of a second.

I am quite new to PHP programming, I would be very grateful if someone can help. I tried flushing the stream after every 128k read, but that didn't work. Am I doing something really stupid?

Thanks in advance.

Posted: Sun Aug 08, 2004 3:55 pm
by timvw
This is how i do it

Code: Select all

header('Content-length: ' . filesize($path));
  header('Content-type: video/' . $extension);
  header('Content-Disposition: attachment; filename=' . $file);
  readfile($path);

Posted: Sun Aug 08, 2004 4:03 pm
by mlynn
Thank you for your suggestion, but that causes the same problem. The stream stops after 251,872 bytes using that one. Letting the script run for longer (30 seconds, 1 minute) doesn't make the output file any longer so it's not as if my machine or reading the file is slow.

Posted: Sun Aug 08, 2004 4:09 pm
by timvw
Ah, have a look at the time_limit and maximum execution time stuff in the php manual ;)

Posted: Sun Aug 08, 2004 4:28 pm
by mlynn
Interesting, the maximum timeout time in PHP.INI is 30 seconds. I have tried calling set_time_limit(10); but it appears that the second call to echo never returns 8O

Might there be a problem with my web server?

Posted: Sun Aug 08, 2004 4:39 pm
by timvw
that is weird

Code: Select all

// may take a long time to finish - 20 * 60 seconds
set_time_limit(1200);
works fine overhere.

Posted: Sun Aug 08, 2004 5:01 pm
by mlynn
After continual approximation I have found that the file size that causes the problem is anything more than 251851 bytes. Less than that the script takes less than one second to execute, after that the second call to echo does not return. I'm confused.

Posted: Sun Aug 08, 2004 11:23 pm
by feyd
that may be your php's upload or post maximum length you are hitting.. maybe..

Posted: Mon Aug 09, 2004 12:36 pm
by mlynn
I have been able to try my script using IIS5 on Windows 2000 and it works fine there. I don't think it is a PHP problem, I'd like my script to work with BadBlue.

It looks more like some limit in BadBlue 2.5 but I don't know of any other way to stream data back other than using echo or print. It did the same with BadBlue 2.1

Posted: Thu Aug 12, 2004 12:30 pm
by mlynn
I have found a solution to my problem :)


BadBlue allocates 256K of output for each PHP script by default.
A setting can be added to the BadBlue EXT.INI file as follows:

[services]
maxcgioutput=9000000

or whatever the largest file delivered via PHP is (size is in bytes).
My EXT.INI file had no maxcgioutput setting.

This solution was posted on the Bad Blue forum:
http://p080.ezboard.com/bbadbluediscuss

Thank you for your suggestions and help.