You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让PHP脚本在接收大文件上传时同步执行?

解决Apache+PHP(非FastCGI)大文件上传实时处理缓冲问题

问题根源

你遇到的核心问题是Apache默认会将完整的请求体(即便是chunked编码)缓冲到磁盘或内存后,才会转发给mod_php模块执行脚本,导致PHP代码要等上传100%完成后才启动,无法在上传过程中通过php://input实时处理数据。


解决方案步骤

1. 修改Apache配置,禁用请求体缓冲

在Apache的虚拟主机配置文件(如/etc/apache2/sites-available/000-default.conf)或全局httpd.conf中添加以下配置:

# 强制Apache不缓冲请求体,直接传递给PHP
SetEnv no-buffering 1
# 禁用请求体的gzip压缩,避免额外缓冲
SetEnv no-gzip 1
# 关闭TCP_DEFER_ACCEPT,防止Apache等待完整请求再处理
AcceptFilter http none

修改后重启Apache服务(Docker容器内执行apache2ctl restart)。

2. 调整PHP配置,关闭自动POST数据解析

编辑php.ini文件,修改以下参数:

# 仅解析GET和COOKIE变量,跳过POST自动解析
request_order = "GP"
# 完全关闭PHP自动读取POST数据到$_POST的功能
enable_post_data_reading = Off

这一步是关键——如果开启enable_post_data_reading,PHP会自动读取整个php://input内容填充$_POST,强制触发缓冲。

3. 编写实时处理的PHP脚本

使用流式读取方式处理php://input,避免一次性加载全部数据到内存,示例代码如下:

<?php
// 脚本启动立即打日志,验证是否实时触发
error_log("上传流程启动,开始接收数据");

// 开启隐式刷新,确保实时输出(如果需要给客户端返回进度)
ob_implicit_flush(true);
ob_end_flush();

// 打开输入流
$inputStream = fopen('php://input', 'rb');
if (!$inputStream) {
    error_log("无法打开php://input流");
    http_response_code(500);
    exit;
}

// 打开目标输出文件
$targetPath = '/var/www/uploads/large_file.dat';
$outputStream = fopen($targetPath, 'wb');
if (!$outputStream) {
    error_log("无法创建目标文件:{$targetPath}");
    fclose($inputStream);
    http_response_code(500);
    exit;
}

// 分块读取并写入,每次处理4MB数据
$chunkSize = 4 * 1024 * 1024;
$totalBytes = 0;
while (!feof($inputStream)) {
    $chunk = fread($inputStream, $chunkSize);
    if ($chunk === false) {
        error_log("读取数据块失败");
        break;
    }
    fwrite($outputStream, $chunk);
    $totalBytes += strlen($chunk);
    // 实时记录上传进度
    error_log("已接收:{$totalBytes} 字节");
}

// 关闭流资源
fclose($inputStream);
fclose($outputStream);

error_log("上传完成,总接收字节数:{$totalBytes}");
http_response_code(200);
echo "上传成功";
?>

4. Docker环境额外注意事项

  • 确保Apache配置修改在容器中生效:如果使用官方Apache+PHP镜像,可以通过Dockerfile复制自定义配置文件,或在docker-compose.yml中挂载宿主机的配置文件到容器对应目录。
  • 磁盘空间:虽然上传期间内存稳定,但要确保容器挂载的存储目录有足够空间容纳大文件,避免磁盘耗尽导致上传失败。

内容的提问来源于stack exchange,提问作者Simao Gomes Viana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:10:17