php - 使用 PHP 下载一个 2 GB 的文件

标签 php

我已经编写了一个用于从服务器下载文件的 PHP 页面。文件名在 URL 中作为 GET 变量传递,然后以下代码提供文件以供下载:

$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);

注意:我正在使用 exec() 调用,因为大多数文件都很大 (>2GB),而较大的文件会导致 filesize() 和 stat() 函数失败。

无论如何,此代码对几乎所有文件都适用。但是,当文件的大小恰好为 2 GB(2147483648 字节)时,不会发送 header 并且浏览器会尝试下载 PHP 页面本身,这会导致保存名为 download.php 的空文件.

这是我用 curl 测试时发生的情况:

测试 #1:获取一个名为 bigfile1 的 1 GB 文件:

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

测试 #2:获取一个名为 bigfile2 的 2 GB 文件

$ curl -v http://<SERVER>/download.php?id=bigfile2
* About to connect() to <SERVER> port 80 (#0)
*   Trying <IP_ADDRESS>... connected
* Connected to <SERVER> (<IP_ADDRESS>) port 80 (#0)
> GET /download.php?id=bigfile2 HTTP/1.1
> 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
> Host: <SERVER>
> Accept: */*
>
* Empty reply from server
* Connection #0 to host <SERVER> left intact
curl: (52) Empty reply from server
* Closing connection #0

我创建了大小为 1 GB、2 GB、3 GB、4 GB 和 5 GB 的测试文件。 2 GB 的文件是导致此行为的唯一文件,但它始终如一地发生,而且似乎与客户端浏览器或操作系统无关。服务器正在运行 Debian GNU/Linux 4.0、Apache 2.2.4 和 PHP 5.3.0。

任何想法将不胜感激。谢谢!

最佳答案

在 64 位安装中,使用 PHP 5.3.6 时我没有遇到你提到的文件大小问题。 32 位安装给了我:

failed to open stream: Value too large for defined data type

但话虽如此,我什至不会使用 readfile。相反:

header("X-Sendfile: $filepath/$filename");

需要安装和配置mod_xsendfile。

关于php - 使用 PHP 下载一个 2 GB 的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6431100/

相关文章:

php - 使用 "AS score"从mysql全文搜索返回相关性分数

php - 将 JavaScript 函数转换为 PHP 函数(用于将字符串转换为 HTML 编码文本)

php - 打开数据库记录时,不允许其他用户更改记录(PHP+MySQL)

php - jQ Grid 编辑表单的问题不向 SQL 数据库发送请求

php - mysqli_fetch_assoc()期望参数/调用成员函数bind_param()错误。如何获取并修复实际的mysql错误?

PHP 静态方法与非静态方法/标准函数

php - 使用 INFORMATION_SCHEMA 作为根,错误说它不存在?

php - 强制浏览器缓存图片

PHP XMLReader - 访问 ELEMENT 常量但出现 T_PAAMAYIM_NEKUDOTAYIM 错误

php - 从 magento 模块创建一个新表