如何基于PHP的curl_multi_exec实现多文件并行上传?含Request类框架
PHP多文件并行上传实现方案
我来帮你完善这个基于cURL多句柄实现的PHP多文件并行上传方案!你的Request类框架已经搭好了核心结构,下面是补全后的完整实现:
完整的Request类代码
class Request { protected $curlHandlers = []; protected $curlMultiHandle = null; public function register($url, $file = []) { if (empty($file) || !is_array($file)) { return false; } // 仅初始化一次多cURL句柄 if (is_null($this->curlMultiHandle)) { $this->curlMultiHandle = curl_multi_init(); } // 为每个待上传文件创建独立cURL句柄 foreach ($file as $fieldName => $filePath) { if (!file_exists($filePath)) { trigger_error("文件 {$filePath} 不存在,跳过上传", E_USER_WARNING); continue; } $curlHandler = curl_init($url); // 配置POST上传参数(使用CURLFile符合PHP5.5+安全规范) $postData = [ $fieldName => new CURLFile(realpath($filePath)) ]; curl_setopt($curlHandler, CURLOPT_POST, true); curl_setopt($curlHandler, CURLOPT_POSTFIELDS, $postData); // 设置返回结果不直接输出,后续统一收集 curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, true); // 可选:设置上传超时时间(单位:秒) curl_setopt($curlHandler, CURLOPT_TIMEOUT, 30); // 将单个句柄添加到多句柄队列 curl_multi_add_handle($this->curlMultiHandle, $curlHandler); $this->curlHandlers[] = $curlHandler; } return true; } public function executeAll() { if (is_null($this->curlMultiHandle) || empty($this->curlHandlers)) { return []; } $activeHandles = null; // 启动多cURL请求执行 do { $execStatus = curl_multi_exec($this->curlMultiHandle, $activeHandles); } while ($execStatus == CURLM_CALL_MULTI_PERFORM); // 等待所有请求完成 while ($activeHandles && $execStatus == CURLM_OK) { if (curl_multi_select($this->curlMultiHandle) == -1) { usleep(100); // 避免CPU空转 } do { $execStatus = curl_multi_exec($this->curlMultiHandle, $activeHandles); } while ($execStatus == CURLM_CALL_MULTI_PERFORM); } // 收集所有上传结果并清理资源 $uploadResults = []; foreach ($this->curlHandlers as $handler) { $uploadResults[] = [ 'response' => curl_multi_getcontent($handler), 'error_msg' => curl_error($handler), 'error_code' => curl_errno($handler) ]; // 移除并关闭单个cURL句柄 curl_multi_remove_handle($this->curlMultiHandle, $handler); curl_close($handler); } // 关闭多cURL句柄并重置属性 curl_multi_close($this->curlMultiHandle); $this->curlMultiHandle = null; $this->curlHandlers = []; return $uploadResults; } }
关键细节说明
CURLFile替代旧语法:放弃了不安全的@符号文件上传方式,符合PHP5.5及以上版本的安全规范- 多句柄并行机制:每个文件对应独立的cURL句柄,通过
curl_multi系列函数实现真正的并行上传,比串行上传效率提升明显 - 资源清理:执行完成后必须关闭所有句柄,避免内存泄漏
- 错误处理:收集每个文件的上传错误信息,方便后续排查问题
使用示例
// 初始化上传实例 $uploader = new Request(); // 注册需要上传的文件(支持多个文件同时上传到同一接口) $uploader->register('https://your-upload-api.com/upload', [ 'avatar' => '/home/user/avatar.jpg', 'document' => '/home/user/resume.pdf', 'attachment' => '/home/user/log.zip' ]); // 执行并行上传并获取结果 $results = $uploader->executeAll(); // 遍历处理结果 foreach ($results as $idx => $result) { if ($result['error_code'] === 0) { echo "第{$idx+1}个文件上传成功:{$result['response']}\n"; } else { echo "第{$idx+1}个文件上传失败:{$result['error_msg']}\n"; } }
额外提示
- 若需要上传到不同接口,可多次调用
register方法,每次传入不同的URL和对应文件 - 可根据需求添加更多cURL配置,比如自定义HTTP头、SSL证书验证、进度回调等
- 确保服务器的
max_execution_time和upload_max_filesize配置足够应对大文件上传
内容的提问来源于stack exchange,提问作者Eden Reich
相关产品推荐
相关产品推荐

