Re: [PHP] handling large files w/readfile

2005-02-23 Thread Marek Kilimajer
A little late but:
Robin Getz wrote:
If this runs for awhile things go very bad. This seems to be related to 
a specific download manager called NetAnts that seems to be popular in 
China.
http://www.netants.com/

Which attempts to open the same url for downloading 10-15 times at the 
same instant.

Download managers use Content-Range header [1] to request parts of the 
downloaded file in multiple instances. The client above is likely broken 
 and does not recognize that your script does not support content-range 
requests, and keeps requesting and disconnecting instead of giving up.

Someone suggested apache_child_terminate - but this function doesn't 
seem to be available to me.
If the function is not available you can still use connection_aborted().
[1] http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


Re: [PHP] handling large files w/readfile

2005-01-04 Thread Jason Wong
On Sunday 02 January 2005 16:43, Robin Getz wrote:
 Rasmus Lerdorf wrote:
   
   $buff = 0;
   while (!feof($fp)) {
  $buff = fread($fp, 4096);
  print $buff;
   }
   unset($buff);
   fclose ($fp);
   
 
 Well, the above code does not use more than 4K of ram plus a bit of
 overhead.  So if something is causing your processes to grow to 450M you
 need to look elsewhere because this code is definitely not the cause.

 Well, the test case is:
 1) above with big files = big apache processes - machine crashes

Are you using the above code on its own (ie not within some other code that 
may affect the memory usage)?

-- 
Jason Wong - Gremlins Associates - www.gremlins.biz
Open Source Software Systems Integrators
* Web Design  Hosting * Internet  Intranet Applications Development *
--
Search the list archives before you post
http://marc.theaimsgroup.com/?l=php-general
--
New Year Resolution: Ignore top posted posts

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP] handling large files w/readfile

2005-01-04 Thread Robin Getz
Jason Wong wrote:
Are you using the above code on its own (ie not within some other code 
that may affect the memory usage)?
Well, herethe entire file (It is pretty short - only a 2 pages, but sorry 
in advance if anyone considers this bad form).

site is called with something like
http://blackfin.uclinux.org/frs/download.php/123/STAMP.jpg
Files are stored in:
$sys_upload_dir.$group_name.'/'.$filename
-- frs/download.php -
?php
/**
 * GForge FRS Facility
 *
 * Copyright 1999-2001 (c) VA Linux Systems
 * The rest Copyright 2002-2004 (c) GForge Team
 * http://gforge.org/
 *
 * @version   $Id: download.php,v 1.6 2004/10/08 23:05:29 gsmet Exp $
 *
 * This file is part of GForge.
 *
 * GForge is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * GForge is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GForge; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
MA  02111-1307  USA  */

$no_gz_buffer=true;
require_once('pre.php');
$arr=explode('/',$REQUEST_URI);
$file_id=$arr[3];
$res=db_query(SELECT frs_file.filename,frs_package.is_public,
frs_file.file_id,groups.unix_group_name,groups.group_id
FROM frs_package,frs_release,frs_file,groups
WHERE frs_release.release_id=frs_file.release_id
AND groups.group_id=frs_package.group_id
AND frs_release.package_id=frs_package.package_id
AND frs_file.file_id='$file_id');
if (db_numrows($res)  1) {
Header(Status: 404);
exit;
}
$is_public =db_result($res,0,'is_public'); 
$group_name=db_result($res,0,'unix_group_name');
$filename = db_result($res,0,'filename'); 
$release_id=db_result($res,0,'release_id');
$group_id = db_result($res,0,'group_id');

$Group = group_get_object($group_id);
if (!$Group || !is_object($Group) || $Group-isError()) {
exit_no_group();
}
if(!$Group-isPublic()) {
session_require(array('group' = $group_id)); }
//  Members of projects can see all packages //  Non-members can only see 
public packages
if(!$is_public) {
if (!session_loggedin() || (!user_ismember($group_id)  
!user_ismember(1,'A'))) {
exit_permission_denied();
}
}

/*
echo $group_name.'|'.$filename.'|'.$sys_upload_dir.$group_name.'/'.$filename;
if (file_exists($sys_upload_dir.$group_name.'/'.$filename)) {
echo 'br /file exists';
passthru($sys_upload_dir.$group_name.'/'.$filename);
}
*/
if (file_exists($sys_upload_dir.$group_name.'/'.$filename)) {
Header('Content-disposition: filename='.str_replace('', '', 
$filename).'');
Header(Content-type: application/binary);
length = filesize($sys_upload_dir.$group_name.'/'.$filename);
Header(Content-length: $length);

# Here is where all the problems start
readfile($sys_upload_dir.$group_name.'/'.$filename);
if (session_loggedin()) {
s = session_get_user();
us=$s-getID();
} else {
us=100;
}
res=db_query(INSERT INTO frs_dlstats_file 
(ip_address,file_id,month,day,user_id)
VALUES 
('$REMOTE_ADDR','$file_id','.date('Ym').','.date('d').','$us'));
} else {
Header(Status: 404);
}

?
=
If this runs for awhile things go very bad. This seems to be related to a 
specific download manager called NetAnts that seems to be popular in China.
http://www.netants.com/

Which attempts to open the same url for downloading 10-15 times at the same 
instant.

If I replace things with:
 snip =
if (file_exists($sys_upload_dir.$group_name.'/'.$filename)) {
# if the file is too big to download (10Meg) - use a different 
method than php
   $length = filesize($sys_upload_dir.$group_name.'/'.$filename);
Header('Content-disposition: filename='.str_replace('', '', 
$filename).'');
Header(Content-type: application/binary);
Header(Content-length: $length);

fp = fopen($sys_upload_dir.$group_name.'/'.$filename,'rb');
buff=0;
while (!feof($fp)) {
buff = fread($fp, 4096);
print $buff;
}
unset($buff);
fclose ($fp);
===  snip - rest is the same =
I get exactly the same problem - I come back and there are 2-3-4 apache 
processes that are consuming memory the size of the largest downloads.

The only way I can make things work with large downloads is to use this:
 snip 
if 

Re: [PHP] handling large files w/readfile

2005-01-04 Thread Jason Wong
On Tuesday 04 January 2005 22:04, Robin Getz wrote:
 Jason Wong wrote:
 Are you using the above code on its own (ie not within some other code
 that may affect the memory usage)?

 Well, herethe entire file (It is pretty short - only a 2 pages, but sorry
 in advance if anyone considers this bad form).

I should have added that if you're not running that snippet of code on its own 
then try running it on its own, give it a fixed filename (so you don't have 
to go through the $_REQUEST and database business). Clouding the issue by 
running it in conjunction with other code (however innocuous) just 
complicates matters.

-- 
Jason Wong - Gremlins Associates - www.gremlins.biz
Open Source Software Systems Integrators
* Web Design  Hosting * Internet  Intranet Applications Development *
--
Search the list archives before you post
http://marc.theaimsgroup.com/?l=php-general
--
New Year Resolution: Ignore top posted posts

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] handling large files w/readfile

2005-01-03 Thread Richard Lynch
Sebastian wrote:
 yea. all the files aren't 100MB though.. some are 2mb (even less) while
 some
 files are over 300MB as well.
 so, does this need to be adjusted depending on the filesize?

I believe that at a certain point, your setting there will be worse for
the system if you make it too big instead of too small, regardless of the
filesize to be written/read.

This is because no matter how big your file is, there are buffers all
along the chain of events between http://php.net/fread and the actual
electrical signals re-aligning the magnetic spots on your hard drive disc.

You're defining a buffer for fread.
PHP may have an internal buffer in a layer deeper than that (probably not,
but *could* have one)
The C library may have a buffer in the next layer down.  Again, probably
not, but it *could* have one.
The library inside the OS that the C library is calling maybe has a buffer.
The OS File System that the OS library calls probably has a buffer.
The physical hardware almost for sure has a buffer, probably several.
If you have fancy hardware and/or RAID software, then there are even more
buffers involved.

And, of course, the RAM available to PHP at the time of doing this work
will drastically affect performance -- If your server is loaded, and this
fread with your (possibly over-sized) buffer forces PHP and/or the OS to
swap something in/out to the hard drive, then you are going to KILL your
system.

At every step of the way, the data being buffered in a faster/cheaper
storage medium will have an effect on your performance.

Hopefully, for most uses, that is an overall Good effect.

But nobody on Earth can tell you for sure for sure that it's all optimum
for *YOUR* application's needs on *YOUR* hardware.

So given your OS, and your hard drive and your file system, and your
files, and the usual load on your server (RAM) there is some ideal
number for that collection of hardware/software that you use.

The only way to find your ideal number is to trial and error benchmark it.

I'd try numbers that match up with:
  the cache size on the hard drive
  any internal buffers in PHP's fread() functions
  any buffer in your File System and/or OS of choice
  very large numbers
  very small numbers
  a random assortment of nice numbers (1Mb 2Mb 4Mb ...)

Now, if your code has to run on LOTS of different hardware, you'd want to
benchmark on as many different sets of hardware as you can to find the
ideal number for *most* hardware.

Or, you could, I suppose, try to write a system that detects certain
specific categories of hardware/software and choose your buffer size based
on that.

Now, having said all that, the difference to the performance for MOST
applications is going to be negligible.  Find a number that works fast
enough for your application (with reasonable testing/benchmarking) and
move on with life.

-- 
Like Music?
http://l-i-e.com/artists.htm

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP] handling large files w/readfile

2005-01-02 Thread Robin Getz
Rasmus Lerdorf wrote:
 
 $buff = 0;
 while (!feof($fp)) {
$buff = fread($fp, 4096);
print $buff;
 }
 unset($buff);
 fclose ($fp);
 
Well, the above code does not use more than 4K of ram plus a bit of 
overhead.  So if something is causing your processes to grow to 450M you 
need to look elsewhere because this code is definitely not the cause.
Well, the test case is:
1) above with big files = big apache processes - machine crashes
2) download big files with:
 Header(Location: .$html_pointer_to_file);
   = small apache processes - works great
So, I don't know if it can be anything else but that - so I am open to 
suggestions, or tests that anyone wants me to run.

-Robin 

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


Re: [PHP] handling large files w/readfile

2005-01-01 Thread Sebastian
yea. all the files aren't 100MB though.. some are 2mb (even less) while some
files are over 300MB as well.
so, does this need to be adjusted depending on the filesize?

thanks.

- Original Message - 
From: Rory Browne [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
Cc: Sebastian [EMAIL PROTECTED]; php-general@lists.php.net
Sent: Friday, December 31, 2004 10:24 PM
Subject: Re: [PHP] handling large files w/readfile


 I'd go with Richards Basic idea, but if you're outputting a 100Mb file
 I'd use a hell of a lot bigger chunks than 4K. With the syscall and
 loop overhead, i'd go with at least half a megabyte, or more likely
 2Mb depending on your amount of memory.

 To do this you'd change Richards

 echo fread($fp, 4096); //4K chunks

 to

 echo fread($fp, 2048000); // ~2Mb chunks (actually 2000KB but couldn't
 be bothered counting, and 2Mb is an arbitory figure anyway)

 Just make sure you don't have output buffering on.


 On Fri, 31 Dec 2004 15:17:51 -0800 (PST), Richard Lynch [EMAIL PROTECTED]
wrote:
  Sebastian wrote:
   i'm working on a app which output files with readfile() and some
headers..
   i read a comment in the manual that says if your outputting a file php
   will
   use the same amount of memory as the size of the file. so, if the file
is
   100MB php will use 100MB of memory.. is this true?
  
   if it is, how can i work around this?
 
  I don't know if it's STILL true (or ever was) that readfile() would suck
  the whole file into RAM before spitting it out...  Seems real unlikely,
  but...
 
  At any rate, you can simply do:
 
  $file = 'whatever.mb';
  $fp = @fopen($file, 'r') or trigger_error(Could not read $file,
  E_USER_ERROR);
  while (!feof($fp)){
echo fread($fp, 4096); //4K chunks
  }
 
  http://php.net/fopen http://php.net/fread http://php.net/feof
 
  --
  Like Music?
  http://l-i-e.com/artists.htm
 
  --
  PHP General Mailing List (http://www.php.net/)
  To unsubscribe, visit: http://www.php.net/unsub.php
 
 

 -- 
 PHP General Mailing List (http://www.php.net/)
 To unsubscribe, visit: http://www.php.net/unsub.php




-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] handling large files w/readfile

2005-01-01 Thread Curt Zirzow
* Thus wrote Richard Lynch:
 Sebastian wrote:
  i'm working on a app which output files with readfile() and some headers..
  i read a comment in the manual that says if your outputting a file php
  will
  use the same amount of memory as the size of the file. so, if the file is
  100MB php will use 100MB of memory.. is this true?
 
  if it is, how can i work around this?
 
 I don't know if it's STILL true (or ever was) that readfile() would suck
 the whole file into RAM before spitting it out...  Seems real unlikely,
 but...

Never was and still isn't.

using either readfile or fpassthru is the best route.


Curt
-- 
Quoth the Raven, Nevermore.

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP] handling large files w/readfile

2005-01-01 Thread Robin Getz
Curt Zirzow wrote:
* Thus wrote Richard Lynch:
 Sebastian wrote:
  i'm working on a app which output files with readfile() and some 
headers..
  i read a comment in the manual that says if your outputting a file
  php will use the same amount of memory as the size of the file. so,
  if the file is 100MB php will use 100MB of memory.. is this true?

 I don't know if it's STILL true (or ever was) that readfile() would
 suck the whole file into RAM before spitting it out...  Seems real
 unlikely, but...

Never was and still isn't.
using either readfile or fpassthru is the best route.
All I know that I am hosting a GForge site, and if I leave the download.php 
code as is, I will send up with apache processes that are 200+Meg. (the 
size of my download files).
http://gforge.org/plugins/scmcvs/cvsweb.php/gforge/www/frs/download.php?rev=1.6;content-type=text%2Fplain;cvsroot=cvsroot%2Fgforge

(which uses readfile)
I have tried fpassthru - same thing.
I have even tried:
$fp = fopen($sys_upload_dir.$group_name.'/'.$filename,'rb');
while (!feof($fp)) {
   $buff = fread($fp, 4096);
   print $buff;
}
fclose ($fp);
and I get the same thing. The only thing that seems to work is:
Header(Location: .$html_pointer_to_fp);
which lets apache do the downloading.
I would do a apache_child_terminate, but the function does not seem to be 
available to me (see my previous question about this).

Any thoughts, or suggestions, I am open to try.
My next experiment is:

var $buff;
while (!feof($fp)) {
   $buff = fread($fp, 4096);
   print $buff;
}
unset($buff);
fclose ($fp);

Hopefully that will make sure that the var $buff is only created once, and 
that the memory is cleared after the function is done.

-Robin 

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


RE: [PHP] handling large files w/readfile

2005-01-01 Thread Robin Getz
Robin Getz wrote:
My next experiment is:

$buff = 0;
while (!feof($fp)) {
   $buff = fread($fp, 4096);
   print $buff;
}
unset($buff);
fclose ($fp);

Nope that doesn't work either - came back, and saw apache processes that 
were +450Meg. Changed it back to apache redirection for now.

If anyone has __any__ suggestions, I am more than happy to try. I would 
like to get this figured out.

Thanks
-Robin 

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


Re: [PHP] handling large files w/readfile

2005-01-01 Thread Rasmus Lerdorf
Robin Getz wrote:
Robin Getz wrote:
My next experiment is:

$buff = 0;
while (!feof($fp)) {
   $buff = fread($fp, 4096);
   print $buff;
}
unset($buff);
fclose ($fp);


Nope that doesn't work either - came back, and saw apache processes that 
were +450Meg. Changed it back to apache redirection for now.

If anyone has __any__ suggestions, I am more than happy to try. I would 
like to get this figured out.
Well, the above code does not use more than 4K of ram plus a bit of 
overhead.  So if something is causing your processes to grow to 450M you 
need to look elsewhere because this code is definitely not the cause.

-Rasmus
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


Re: [PHP] handling large files w/readfile

2005-01-01 Thread Sebastian
well, i really can't confirm what your seeing. but that is why i orginally
started this topic. i will do some tests..
are you setting headers before output? i just ran into another problem..
when downloading a .tar file it just returns an empty .tar file.. seems to
work fine with .exe, .zip, tar.gz, but not .tar

any ideas?
this is what im using:

header('Content-type: application/octet-stream');
header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Content-transfer-encoding: binary');
header('Content-Disposition: attachment; filename=' . $file['type'] . '');
header('Content-Length: ' . filesize($file['path'] . $file['type']));
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');

- Original Message - 
From: Robin Getz [EMAIL PROTECTED]
To: php-general@lists.php.net
Sent: Saturday, January 01, 2005 9:38 PM
Subject: RE: [PHP] handling large files w/readfile


 Robin Getz wrote:
 My next experiment is:
 
 $buff = 0;
 while (!feof($fp)) {
 $buff = fread($fp, 4096);
 print $buff;
 }
 unset($buff);
 fclose ($fp);
 

 Nope that doesn't work either - came back, and saw apache processes that
 were +450Meg. Changed it back to apache redirection for now.

 If anyone has __any__ suggestions, I am more than happy to try. I would
 like to get this figured out.

 Thanks
 -Robin

 -- 
 PHP General Mailing List (http://www.php.net/)
 To unsubscribe, visit: http://www.php.net/unsub.php




-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] handling large files w/readfile

2004-12-31 Thread Richard Lynch
Sebastian wrote:
 i'm working on a app which output files with readfile() and some headers..
 i read a comment in the manual that says if your outputting a file php
 will
 use the same amount of memory as the size of the file. so, if the file is
 100MB php will use 100MB of memory.. is this true?

 if it is, how can i work around this?

I don't know if it's STILL true (or ever was) that readfile() would suck
the whole file into RAM before spitting it out...  Seems real unlikely,
but...

At any rate, you can simply do:

$file = 'whatever.mb';
$fp = @fopen($file, 'r') or trigger_error(Could not read $file,
E_USER_ERROR);
while (!feof($fp)){
  echo fread($fp, 4096); //4K chunks
}

http://php.net/fopen http://php.net/fread http://php.net/feof

-- 
Like Music?
http://l-i-e.com/artists.htm

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] handling large files w/readfile

2004-12-31 Thread Rory Browne
I'd go with Richards Basic idea, but if you're outputting a 100Mb file
I'd use a hell of a lot bigger chunks than 4K. With the syscall and
loop overhead, i'd go with at least half a megabyte, or more likely
2Mb depending on your amount of memory.

To do this you'd change Richards 

echo fread($fp, 4096); //4K chunks

to 

echo fread($fp, 2048000); // ~2Mb chunks (actually 2000KB but couldn't
be bothered counting, and 2Mb is an arbitory figure anyway)

Just make sure you don't have output buffering on. 


On Fri, 31 Dec 2004 15:17:51 -0800 (PST), Richard Lynch [EMAIL PROTECTED] 
wrote:
 Sebastian wrote:
  i'm working on a app which output files with readfile() and some headers..
  i read a comment in the manual that says if your outputting a file php
  will
  use the same amount of memory as the size of the file. so, if the file is
  100MB php will use 100MB of memory.. is this true?
 
  if it is, how can i work around this?
 
 I don't know if it's STILL true (or ever was) that readfile() would suck
 the whole file into RAM before spitting it out...  Seems real unlikely,
 but...
 
 At any rate, you can simply do:
 
 $file = 'whatever.mb';
 $fp = @fopen($file, 'r') or trigger_error(Could not read $file,
 E_USER_ERROR);
 while (!feof($fp)){
   echo fread($fp, 4096); //4K chunks
 }
 
 http://php.net/fopen http://php.net/fread http://php.net/feof
 
 --
 Like Music?
 http://l-i-e.com/artists.htm
 
 --
 PHP General Mailing List (http://www.php.net/)
 To unsubscribe, visit: http://www.php.net/unsub.php
 


-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP] handling large files w/readfile

2004-12-26 Thread Sebastian
i'm working on a app which output files with readfile() and some headers..
i read a comment in the manual that says if your outputting a file php will
use the same amount of memory as the size of the file. so, if the file is
100MB php will use 100MB of memory.. is this true?

if it is, how can i work around this?

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] handling large files w/readfile

2004-12-26 Thread Heilig \(Cece\) Szabolcs
Hello!

 i'm working on a app which output files with readfile() and some headers..
 i read a comment in the manual that says if your outputting a file php
 will
 use the same amount of memory as the size of the file. so, if the file is
 100MB php will use 100MB of memory.. is this true?

 if it is, how can i work around this?

Do not use readfile() or file_get_contents() to read
the full file in one step. Read file in smaller chunks
to a buffer variable whith fread() and output that
immediately in the cycle. And again and again...
You can read terrabytes of data and utput them, the
amount of memory needed is based on your buffer size.

-- 
=
Heilig (Cece) Szabolcs - [EMAIL PROTECTED] - http://www.phphost.hu
=

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] handling large files w/readfile

2004-12-26 Thread Raditha Dissanayake
Sebastian wrote:
i'm working on a app which output files with readfile() and some headers..
i read a comment in the manual that says if your outputting a file php will
use the same amount of memory as the size of the file. so, if the file is
100MB php will use 100MB of memory.. is this true?
 

I did a comparision study of readfile() and related functions you will 
see that results at http://www.raditha.com/wiki/Readfile_vs_include
What I discovered was that require,include() and file_get_contents() 
would consume more memory than the file size. Not so with readfile or 
fpasstru


if it is, how can i work around this?
 

go ahead and use readfile.

--
Raditha Dissanayake.
--
http://www.radinks.com/print/card-designer/ | Card Designer Applet
http://www.radinks.com/upload/  | Drag and Drop Upload 

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php