这是我第一次使用
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);
}
一旦它开始工作,我可能会把它分解成函数,但我更喜欢以这种格式编辑损坏的代码,然后再添加函数调用。
以前从未使用过这些功能,我不确定它们应该如何表现,但我注意到的行为:
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"
.https://google.com
会导致一切超时。因此,我的代码至少可以访问互联网。curl_multi_getcontent($curlHandle)
总是返回一个空字符串curl_multi_exec($multiHandle, $index)
总是返回0(之前说是1002是不正确的,1002其实是函数运行后第二个参数$index
的值)$multiHandle
似乎按预期工作。至少,var_dump($multiHandle)
会显示其中所有正确的文件名。我已经为这个问题浪费了一整天的工作时间,但如果这是一个小错别字导致的,我也不会感到惊讶。这是什么?
这只是一个猜测,但如果你的问题是超时,那么你编写的以下循环似乎可能是问题所在:
$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;
}
}