Symfony 7.1.3调用vdocipher API时Curl报operation aborted by callback错误
Symfony 7.1.3调用VdoCipher API上传视频时触发Curl错误:
operation aborted by callback 在Symfony 7.1.3项目中调用VdoCipher API上传视频,流程为先通过PUT请求获取上传凭证,再发起POST请求上传视频文件,POST请求阶段触发Curl错误operation aborted by callback。
相关代码实现
1. createVideo方法
public function createVideo($filePath, $fileMimeType, $fileName) { $title = md5(time() . uniqid() . $fileName); $this->urlAction = "?title={$title}"; $videoResponse = $this->sendDataVdocipher("PUT"); if (empty($videoResponse->clientPayload)) { return null; } $credentials = $videoResponse->clientPayload; $data = [ 'policy' => $credentials->policy, 'key' => $credentials->key, 'x-amz-signature' => $credentials->{'x-amz-signature'}, 'x-amz-algorithm' => $credentials->{'x-amz-algorithm'}, 'x-amz-date' => $credentials->{'x-amz-date'}, 'x-amz-credential' => $credentials->{'x-amz-credential'}, 'success_action_status' => 201, 'success_action_redirect' => '', 'file' => new CURLFile($filePath, $fileMimeType, $fileName), ]; $uploadResponse = $this->sendDataVdocipher( 'POST', $data, 'Content-Type: multipart/form-data', $credentials->uploadLink, false ); if (!$uploadResponse) { $this->deleteVideo($videoResponse->videoId); return null; } return $videoResponse->videoId; }
2. sendDataVdocipher方法
protected function sendDataVdocipher( $method = "GET", $data = null, $header = "Content-Type: application/json", $url = null, $allHeaders = true ) { if (empty($url)) { $url = $this->url . $this->urlAction; } if (empty($header)) { $header = "Content-Type: application/json"; } $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_TIMEOUT, 50); $headers = [$header]; if ($allHeaders) { $headers[] = "Accept: application/json"; $headers[] = "Authorization: Apisecret {$this->token}"; } curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); if ($method == "POST" || $method == "PUT") { curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($curl); $error = curl_error($curl); curl_close($curl); if ($error) { return null; } $responseObj = json_decode($response); return $responseObj ?? true; }
CURLOPT_VERBOSE日志
* Trying 108.139.168.232:443... * Connected to vdo-us-east.s3-accelerate.amazonaws.com (108.139.168.232) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 * ALPN, server did not agree to a protocol * Server certificate: * subject: CN=*.s3-accelerate.amazonaws.com * start date: Dec 19 00:00:00 2023 GMT * expire date: Dec 2 23:59:59 2024 GMT * subjectAltName: host "vdo-us-east.s3-accelerate.amazonaws.com" matched cert's "*.s3-accelerate.amazonaws.com" * issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M01 * SSL certificate verify ok. > POST / HTTP/1.1 Host: vdo-us-east.s3-accelerate.amazonaws.com Accept: */* Transfer-Encoding: chunked Content-Type: multipart/form-data; boundary=------------------------c50e1976b4166e97 Expect: 100-continue * Mark bundle as not supporting multiuse < HTTP/1.1 100 Continue * operation aborted by callback * Closing connection 0
已尝试的排查步骤
- 验证Curl请求的URL、头信息及数据配置正确
- 确认文件上传的CURLFile实例创建正常
- 确保API令牌和端点URL有效
解决方案建议
1. 移除Expect: 100-continue请求头
日志显示服务器返回100 Continue后请求被中止,这是Curl默认发送的头,部分服务器对该头的处理可能存在兼容性问题。在sendDataVdocipher方法中,手动添加空的Expect头来禁用该行为:
// 在$headers数组初始化后添加 $headers[] = 'Expect:';
2. 避免手动设置multipart/form-data头
当POST数据包含CURLFile实例时,Curl会自动生成正确的Content-Type头(包含自动生成的boundary),手动设置的头可能与自动生成的冲突。修改createVideo方法中调用sendDataVdocipher的参数,不传Content-Type头:
$uploadResponse = $this->sendDataVdocipher( 'POST', $data, '', // 留空让Curl自动处理Content-Type $credentials->uploadLink, false );
同时在sendDataVdocipher方法中,当$header为空时不要强制设置默认的application/json:
// 替换原有的header默认处理逻辑 $headers = []; if (!empty($header)) { $headers[] = $header; }
3. 调整超时设置
当前CURLOPT_TIMEOUT设置为50秒,对于大文件上传可能不足,同时添加连接超时设置:
// 在curl_setopt(CURLOPT_TIMEOUT...)后添加 curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($curl, CURLOPT_TIMEOUT, 300); // 改为5分钟
4. 检查是否存在未处理的Curl回调
错误提示operation aborted by callback,可能存在未正确配置的Curl回调(如进度回调)。确保代码中没有设置CURLOPT_PROGRESSFUNCTION或其他回调函数,若有则检查回调逻辑是否会中止请求。
5. 升级Curl版本
旧版本Curl在处理TLS 1.3或分块编码时可能存在bug,升级到服务器上可用的最新稳定版Curl。
内容的提问来源于stack exchange,提问作者Matheus Inacio
相关产品推荐
相关产品推荐

