You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 20:37:16