Jump to content

File too large for fopen


danno74

Recommended Posts

Greetings all!

 

So I have a download page for some apps at our school. Here is the code:

<?php
session_start();

      $software_title="Impatica";
  $date= date("y-m-d");
      $time= date("H:i:s");

if (isset($_SESSION['fullname']))
{

 // record activity in db
      include("inc/insertrecord.php");

 //Location of file, must be out of web root
      $file_location='impatica.exe';
      
      //open file
      $file=fopen($file_location,'r');
      
      //get file size
      $file_size=filesize($file_location);
      
      //read the file
      $content=fread($file,$file_size);
      
      //close the file
      fclose($file);
  
      //supply the right file format      
      header('Content-type: application/exe');
  header('Expires: 0');
  header('Pragma: public');
      
      //force browser to prompt to download file
      //cool option of this header is that allows you to rename the file
      header('Content-Disposition: attachment; filename="impatica.exe"');

      
      //finally echo content
      echo $content;
  

  
}
else

header("Location: https://web");

        
?>

 

At first I got the error that I was out of memory, so I increased it with this line:

ini_set("memory_limit","100M");

 

That was all fine and good until I started trying to use it with some HUGE self extracting exes (750 MB). I had to up the limit to 1,500M in order for it to work. I watched the load on the server steadily increase whilst it was downloading.

 

Is there anyway around this? I simply want to have the file available without the user knowing the direct link to where it resides. I greatly appreciate any suggestions. Also, I tried this as a suggestion I found on another forum, and for some reason it used the same amount of memory  :shrug:(according the error log anyhow):

$total = filesize($filepath);
$blocksize = (2 << 20); //2M chunks
	$sent = 0;
$handle = fopen($filepath, "r");

// Push headers that tell what kind of file is coming down the pike
header('Content-type: application/exe');
header('Content-Disposition: attachment; filename='.$software_title);
header('Content-length: '.$total * 1024);

// Now we need to loop through the file and echo out chunks of file data
// Dumping the whole file fails at > 30M!
while($sent < $total){
echo fread($handle, $blocksize);
$sent += $blocksize;

 

Thank you!

Link to comment
Share on other sites

don't read it in to a variable...just use readfile()

 

<?php
  session_start();

  $software_title="Impatica";
  $date= date("y-m-d");
  $time= date("H:i:s");

  if (isset($_SESSION['fullname']))
  {
   
    // record activity in db
    include("inc/insertrecord.php");
    
    //Location of file, must be out of web root
    $file_location='impatica.exe';
      
    //supply the right file format      
    header('Content-type: application/exe');
    header('Expires: 0');
    header('Pragma: public');
      
    //force browser to prompt to download file
    //cool option of this header is that allows you to rename the file
    header('Content-Disposition: attachment; filename="impatica.exe"');
   
      
    //finally echo content
    readfile($file_location);
    exit;
  }
  else
  {
    header("Location: https://web");
  }
  exit;
?>

Link to comment
Share on other sites

Thanks Aaron!

 

It worked with my two smaller files, no memory adjustments necessary. But I still get an error with the larger one:

[Tue Aug 18 15:49:49 2009] [error] [client x] PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 133959681 bytes) in /title2.php on line 28

 

Do I still need to set the memory with this one?

 

Link to comment
Share on other sites

hum...how about this:

<?php
  session_start();

  $software_title="Impatica";
  $date= date("y-m-d");
  $time= date("H:i:s");

  if (isset($_SESSION['fullname']))
  {
   
    // record activity in db
    include("inc/insertrecord.php");
    
    //Location of file, must be out of web root
    $file_location='impatica.exe';
      
    //supply the right file format      
    header('Content-type: application/exe');
    header('Expires: 0');
    header('Pragma: public');
      
    //force browser to prompt to download file
    //cool option of this header is that allows you to rename the file
    header('Content-Disposition: attachment; filename="impatica.exe"');

    //open file
    $file=fopen($file_location,'r');
      
    while(!feof($file) && $cur<$end)
    {
      print fread($file,min(1024*16,$end-$cur));
      $cur+=1024*16;
    }

    //close the file
    fclose($file);
  }
  else
  {
    header("Location: https://web");
  }
  exit;
?>

Link to comment
Share on other sites

If you have output buffering turned on, then PHP will internally buffer the file before sending it to the client.  If that is the case, it doesn't matter how you try and break the file up in your code because PHP will still be holding onto it until you run out of memory.

 

I've seen, but do not have handy, solutions where all output buffering is turned off and in your file read/echo loop you constantly echo and flush so it is all sent immediately.

 

However, there may be a more simple solution if you're on a *nix OS, which may not work but could be worth a shot.  Apache should resolve links to the actual resources, so when a file is requested just create a new link to it and redirect the user to the link.  Then create a cron job or something else to periodically remove links.  Like I said, it may not work at all, but I'd try it if it's appropriate to your environment.

Link to comment
Share on other sites

Thanks again, Aaron. $cur and $end are not defined, and so the log is sending an error stating this. How would I define those?

 

Roopurt - I am running on Solaris 10, so a solution through apache may be a possibility. Or I can just split the file up. I'm getting to that point, this project is really not that high a priority and taking up too much of my time. I would like to learn more about apache... thanks for sharing your thoughts.

Link to comment
Share on other sites

  • 3 weeks later...
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.