Download a 2 GB file using PHP
<p>I have written a PHP page for downloading files from the server.  The name of the file is passed as a GET variable in the URL, and then the following code serves up the file for download:</p>

<pre><code>$filepath = "/path/to/files";
$filename = $_GET['id'];

if( ! file_exists($filepath . "/" . $filename) )
{
    header("HTTP/1.1 404 Not Found");
    @session_destroy();
    exit(0);
}

$cmd = '/usr/bin/stat -c "%s" ' . $filepath . "/" . $filename;
$out = array();
$ret = 0;

exec( $cmd, $out, $ret );

header('Content-type: application/octet-stream');
header('Content-Length: ' . $out[0]);
header('Content-Disposition: attachment; filename="' . $filename . '"');

readfile($filepath . "/" . $filename);
</code></pre>

<p>NOTE: I am using the exec() call because most of the files are large (>2GB) and the larger files caused the filesize() and stat() functions to fail.</p>

<p>Anyway, this code works perfectly for almost all of the files.  However, when a file is <em>exactly</em> 2 GB in size (2147483648 bytes), no headers are sent and the browser attempts to download the PHP page itself, which results in a empty file being saved called download.php.</p>

<p>Here's what happened when I tested this with curl:</p>

<p>Test #1: Get a 1 GB file called bigfile1:</p>

<pre><code>$ curl -v http://&lt;SERVER&gt;/download.php?id=bigfile1
* About to connect() to &lt;SERVER&gt; port 80 (#0)
*   Trying &lt;IP_ADDRESS&gt;... connected
* Connected to &lt;SERVER&gt; (&lt;IP_ADDRESS&gt;) port 80 (#0)
&gt; GET /download.php?id=bigfile1 HTTP/1.1
&gt; User-Agent: curl/7.18.2 (i486-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.8 libssh2/0.18
&gt; Host: &lt;SERVER&gt;
&gt; Accept: */*
&gt;
&lt; HTTP/1.1 200 OK
&lt; Date: Tue, 21 Jun 2011 19:10:06 GMT
&lt; Server: Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.8c PHP/5.3.0
&lt; X-Powered-By: PHP/5.3.0
&lt; Set-Cookie: PHPSESSID=382769731f5e3782e3c1e3e14fc8ae71; path=/
&lt; Expires: Thu, 19 Nov 1981 08:52:00 GMT
&lt; Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
&lt; Pragma: no-cache
&lt; Content-Length: 1073741824
&lt; Content-Disposition: attachment; filename="bigfile1"
&lt; Content-Type: application/octet-stream
&lt;
* Connection #0 to host &lt;SERVER&gt; left intact
* Closing connection #0
</code></pre>

<p>Test #2: Get a 2 GB file called bigfile2</p>

<pre><code>$ curl -v http://&lt;SERVER&gt;/download.php?id=bigfile2
* About to connect() to &lt;SERVER&gt; port 80 (#0)
*   Trying &lt;IP_ADDRESS&gt;... connected
* Connected to &lt;SERVER&gt; (&lt;IP_ADDRESS&gt;) port 80 (#0)
&gt; GET /download.php?id=bigfile2 HTTP/1.1
&gt; User-Agent: curl/7.18.2 (i486-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.8 libssh2/0.18
&gt; Host: &lt;SERVER&gt;
&gt; Accept: */*
&gt;
* Empty reply from server
* Connection #0 to host &lt;SERVER&gt; left intact
curl: (52) Empty reply from server
* Closing connection #0
</code></pre>

<p>I have created test files which are 1 GB, 2 GB, 3 GB, 4 GB, and 5 GB in size.  The 2 GB file is the only one that causes this behavior, but it happens consistently, and it seems to happen regardless of the client browser or OS.  The server is running Debian GNU/Linux 4.0, Apache 2.2.4, and PHP 5.3.0.</p>

<p>Any ideas would be greatly appreciated.  Thanks!</p>
