【问题标题】:Async Upload Using Curl in PHP - curl_multi_exec()在 PHP 中使用 Curl 进行异步上传 - curl_multi_exec()
【发布时间】:2018-04-28 15:10:45
【问题描述】:

几天来,我一直在试图弄清楚如何使用 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
 )
"
}

print_r($_POST) on upload.php 会返回以下响应:

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] => 
)
"
}

感谢任何回答。

谢谢,

伊甸园

【问题讨论】:

    标签: php curl asynchronous upload


    【解决方案1】:

    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 核心。有关如何处理 $_FILES,请参阅 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

    【讨论】:

    • 非常感谢!我发现主要问题是我没有使用 CurlFile...找到这篇文章:stackoverflow.com/questions/21905942/…
    • 另外感谢使用 curl_multi_select 的提示,我会检查一下!
    猜你喜欢
    • 1970-01-01
    • 2010-10-30
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多