我可以让 curl_init() 工作,但不能让 curl_multi_init() 工作

问题描述 投票:0回答:1

这是我第一次使用

curl_multi_init()
所以我可能误解了什么。学习正确使用它对我来说比解决我的问题更重要,因为这个特定的功能将解决我未来的很多问题。

这个特别的电话是为了上传 Etsy 照片。此调用的 Etsy 文档 here.

在 Postman 中运行良好。邮递员为“PHP - cURL”生成的代码片段工作正常。即使在我对其进行编辑后,它仍能正常工作。

问题是,我有超过一千张高分辨率图片要上传,因此无论我的 php.ini 设置多么慷慨,从头到尾运行整个片段,然后循环一千次都会超时。

所以,我逐行将现有代码与同步片段合并,我一定做错了什么。这个例子几乎就是实时代码。我刚刚删除/简化了不相关的内容并编辑了个人信息。 (希望我没有删除/简化错误。):

<?php
include_once 'databaseStuff.php';
include_once 'EtsyTokenStuff.php';
$result = mysqli_query($conn, "SELECT product, listing_id, alt_text, dataStuff;");
$multiCurl = [];
$multiResult = [];
$multiHandle = curl_multi_init();
if (mysqli_num_rows($result) > 0){
    while ($row = mysqli_fetch_assoc($result)){
        for($image = 1; $image <=2; $image++){
            $multiCurl[$row['product'] . "_" . $image] = curl_init();
            curl_setopt_array($multiCurl[$row['product'] . "_" . $image], 
                array(
                    CURLOPT_URL => "https://openapi.etsy.com/v3/application/shops/$myShopNumber/listings/" . $row['listing_id'] . "/images",
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_ENCODING => '',
                    CURLOPT_MAXREDIRS => 10,
                    CURLOPT_TIMEOUT => 0,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                    CURLOPT_CUSTOMREQUEST => 'POST',
                    CURLOPT_POSTFIELDS => array(
                        "image" => new CURLFILE(
                            [
                                1 => "img/imagePathStuff/" . $row['product'] . ".jpg",
                                2 => "img/differentImagePathStuff/" . $row['product'] . ".jpg"
                            ][$image]
                        ),
                        // "listing_image_id" =>,
                        "rank" => $image,
                        "overwrite" => true,
                        // "is_watermarked" =>,
                        "alt_text" => $row['alt_text']
                    ),
                    CURLOPT_HTTPHEADER => array(
                        "x-api-key: $myAPIKey",
                        "authorization: Bearer {$etsyAccessToken}"
                    ),
                )
            );
            curl_multi_add_handle($multiHandle, $multiCurl[$row['product'] . "_" . $image]);
        }
    }
    $index = null;
    do {
        curl_multi_exec($multiHandle, $index);
    } while($index > 0);
    foreach($multiCurl as $k => $curlHandle){
        $multiResult[$k] = curl_multi_getcontent($curlHandle);
        curl_multi_remove_handle($multiHandle, $curlHandle);
    }
    curl_multi_close($multiHandle);
}

一旦它开始工作,我可能会把它分解成函数,但我更喜欢以这种格式编辑损坏的代码,然后再添加函数调用。

以前从未使用过这些功能,我不确定它们应该如何表现,但我注意到的行为:

  • New Insight(21-2-2023):按照@Kazz 的建议,
    while (false !== ($info = curl_multi_info_read($multiHandle))) { print_r($info); }
    为每个项目返回
    Array ( [msg] => 1 [result] => 7 [handle] => Resource id #1009 )
    (每个结果的每个资源 ID +1)。
    7
    对应错误
    "CURLE_COULDNT_CONNECT"
    .
  • New Insight(21-2-2023):虽然几乎每一个变化看起来都是无关紧要的,但将 url 更改为
    https://google.com
    会导致一切超时。因此,我的代码至少可以访问互联网。
  • 所有代码都执行,从头到尾,没有致命错误。
  • do-while 循环执行一次然后再循环一次。 (也许它应该或者它应该每张照片循环一次。无法在任何地方澄清。)
  • 应该更新照片了。不幸的是,第一次测试是在非常小的编辑上进行的,但是再次尝试包括故意错误的照片我至少知道那张特定的照片没有更新,所以可能没有更新。
  • curl_multi_getcontent($curlHandle)
    总是返回一个空字符串
  • curl_multi_exec($multiHandle, $index)
    总是返回0(之前说是1002是不正确的,1002其实是函数运行后第二个参数
    $index
    的值)
  • 这个特定的调用通常对 201 有非常详细的响应,并且至少返回 400、401、403、404、409 和 500 的错误,但我认为我的代码还不足以进行调用。我什至还没有弄清楚如何获得响应代码。
  • 对于将一千多个高分辨率图像从我的服务器传输到 Etsy 的服务器的脚本,它的执行速度肯定非常快。
  • $multiHandle
    似乎按预期工作。至少,
    var_dump($multiHandle)
    会显示其中所有正确的文件名。

我已经为这个问题浪费了一整天的工作时间,但如果这是一个小错别字导致的,我也不会感到惊讶。这是什么?

php php-curl etsy
1个回答
0
投票

这只是一个猜测,但如果你的问题是超时,那么你编写的以下循环似乎可能是问题所在:

    $index = null;
    do {
        curl_multi_exec($multiHandle, $index);
    } while($index > 0);

您正在重复调用

curl_multi_exec
,这在您等待所有上传完成时一直在消耗 CPU。相反,您应该只定期检查上传状态并在两者之间进入等待状态。这应该会减少您的总 CPU 时间:

    while (TRUE) {
        $status = curl_multi_exec($multiHandle, $activeCount);
        if ($status == CURLM_OK && $activeCount) {
            // Wait some time before checking again:
            curl_multi_select($mh, $timeout=1.0);
        }
        else {
            break;
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.