php - 在 PHP 中使用 Curl 进行异步上传 - curl_multi_exec()
问题描述
几天来,我一直在试图弄清楚如何使用 PHP 并行上传多个文件。
假设我有一个名为 Request 的类,它有 2 个方法 register() 和 executeAll():
class Request
{
protected $curlHandlers = [];
protected $curlMultiHandle = null;
public function register($url , $file = [])
{
if (empty($file)) {
return;
}
// Register the curl multihandle only once.
if (is_null($this->curlMultiHandle)) {
$this->curlMultiHandle = curl_multi_init();
}
$curlHandler = curl_init($url);
$options = [
CURLOPT_ENCODING => 'gzip',
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $file,
CURLOPT_USERAGENT => 'Curl',
CURLOPT_HTTPHEADER => [
'Content-Type' => 'multipart/form-data; boundry=-------------'.uniqid()
]
];
curl_setopt_array($curlHandler, $options);
$this->curlHandlers[] = $curlHandler;
curl_multi_add_handle($this->curlMultiHandle, $curlHandler);
}
public function executeAll()
{
$responses = [];
$running = null;
do {
curl_multi_exec($this->curlMultiHandle, $running);
} while ($running > 0);
foreach ($this->curlHandlers as $id => $handle) {
$responses[$id] = curl_multi_getcontent($handle);
curl_multi_remove_handle($this->curlMultiHandle, $handle);
}
curl_multi_close($this->curlMultiHandle);
return $responses;
}
}
$request = new Request;
// For this example I will keep it simple uploading only one file.
// that was posted using a regular HTML form multipart
$resource = $_FILES['file'];
$request->register('http://localhost/upload.php', $resource);
$responses = $request->executeAll(); // outputs an empty subset of array(1) { 0 => array(0) { } }
问题:
无法弄清楚为什么在 upload.php 上(脚本是我在注册方法上的端点 url) $_FILES 始终是一个空数组:
上传.php:
<?php
var_dump($_FILES); // outputs an empty array(0) { }
我已经尝试过的事情:
在数据前加上 @ 前缀,如下所示:
$options = [
CURLOPT_ENCODING => 'gzip',
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => ['file' => '@'.$file['tmp_name']],
CURLOPT_USERAGENT => 'Curl',
CURLOPT_HTTPHEADER => [
'Content-Type' => 'multipart/form-data; boundry=-------------'.uniqid()
]
];
不幸的是,这没有用。
我究竟做错了什么 ?
如何在已发布的脚本 (upload.php) 上获取存储在全局 $_FILES 中的文件资源?
更多调试信息:
在 upload.php print_r 上,我得到以下响应的标题:
array(1) {
[0]=>
string(260) "Array
(
[Host] => localhost
[User-Agent] => Curl
[Accept] => */*
[Accept-Encoding] => gzip
[Content-Length] => 1106
[Content-Type] => multipart/form-data; boundary=------------------------966fdfac935d2bba
[Expect] => 100-continue
)
"
}
upload.php 上的 print_r($_POST) 返回以下响应:
array(1) {
[0]=>
string(290) "Array
(
[name] => example-1.jpg
[encrypted_name] => Nk9pN21IWExiT2VlNnpHU3JRRkZKZz09.jpg
[type] => image/jpeg
[extension] => jpg
[tmp_name] => C:\xampp\tmp\php77D7.tmp
[error] => 0
[size] => 62473
[encryption] => 1
[success] =>
[errorMessage] =>
)
"
}
我很感激任何答案。
谢谢,
伊甸园
解决方案
Can't figure out why on upload.php (the script which is my endpoint url on the register method) $_FILES is always an empty array
- 你的第一个问题是你用你自己的覆盖了 libcurl 的边界字符串,但是你让 curl 自动生成 multipart/form-data 正文,这意味着 curl 在实际的请求正文中生成另一个与你自己不同的随机边界字符串,这意味着服务器将无法解析文件。从标题中删除自定义边界字符串(如果您不覆盖它,curl 将插入它自己的)。您的第二个问题是您使用 $_FILES 错误,如果您希望将其提供给 curl,则需要提取上传名称,并且您需要将文件名转换为 CURLFile 对象以让 curl 为您上传它们。另一个问题是您的脚本在执行多句柄时将无缘无故地使用 100% cpu,您应该添加 curl_multi_select 以防止阻塞整个 cpu 核心。http://php.net/manual/en/features.file-upload.post-method.php
,有关如何使用 CURLFile,请参阅http://php.net/manual/en/curlfile.construct.php和如何使用 curl_multi_select,参见http://php.net/manual/en/function.curl-multi-select.php
推荐阅读
- arrays - 如何显示数组中的图片
- linkedin-api - 在Linkedin上分享文章
- java - 如何知道通过rabbit mq发送的消息的优先级
- python - 使用 google pubsub 的 Python 应用程序被 linux 内核杀死,内存不足
- windows - 用于选择默认打印机的 Windows 应用程序
- airflow - 无法在 Airflow 的自定义运算符中传递 xcom
- python - 基于python源码创建python虚拟环境
- python - 正则表达式:识别缺少空格的字符串
- javascript - 如何将相同的元素推入一个空数组
- python - TypeError: Int' 对象在调用 Bert 方法以生成嵌入时不可调用