You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何扩展Symfony HTTP Client请求函数以支持上传流(二进制数据)

如何扩展Symfony HTTP Client请求函数以支持上传流(二进制数据)

嘿,刚好我对Symfony HTTP Client这块功能熟得很,给你梳理下怎么轻松扩展你的请求函数,支持直接上传二进制数据(比如流形式),完全匹配你说的那种把二进制直接放请求体的场景(比如Azure的Put Blob)。

其实Symfony HTTP Client本身就原生支持多种请求体类型,不用额外写复杂的处理逻辑,我们只需要微调下函数的参数兼容和细节配置就行:

核心原理

Symfony HTTP Client的request方法的body参数,除了字符串,还直接支持:

  • 流资源(比如fopen()返回的资源)
  • SplFileObject对象
  • 甚至是生成器(用于更复杂的分块场景)

这意味着我们可以直接把二进制流或者文件对象传给body,客户端会自动处理流式上传,不会把整个文件加载到内存里——这对大文件特别友好。

修改你的请求函数

我们只需要微调原来的函数,让它兼容不同类型的$body,同时做好请求头的适配:

function sendRequest($client, string $method, string $url, $body = null, array $headers = [], array $query = [], int $timeout = 120) {
    // 自动补充Content-Type:如果没指定且body是流/文件,默认用二进制流的类型
    if (!isset($headers['Content-Type']) && (is_resource($body) || $body instanceof \SplFileObject)) {
        $headers['Content-Type'] = 'application/octet-stream';
    }

    $response = $client->request($method, $url, [
        'headers' => [
            'Authorization' => "Bearer $accessToken",
            'Accept' => $acceptContentType,
            'x-ms-client-request-id' => Traceability::getRequestId(),
            ...$headers,
        ],
        'body' => $body, // 直接传入即可,Symfony会自动识别类型处理
        'query' => $query,
        'timeout' => $timeout
    ]);

    return $response;
}

几种常见的使用场景

1. 上传本地二进制文件(流式)

如果是本地的文件,直接用流或者SplFileObject传入就行,不会占内存:

// 方式1:用fopen打开二进制流
$fileStream = fopen('/path/to/your/blob-file.bin', 'rb');
$response = sendRequest($client, 'PUT', $yourBlobUrl, $fileStream);

// 方式2:用SplFileObject更面向对象
$file = new \SplFileObject('/path/to/your/blob-file.bin', 'rb');
$response = sendRequest($client, 'PUT', $yourBlobUrl, $file);

2. 上传内存中的二进制数据

如果二进制数据已经在内存里(比如从数据库读取的Blob字段),直接传二进制字符串就行,记得指定正确的Content-Type:

// 假设$binaryData是从数据库取出的二进制内容
$response = sendRequest($client, 'PUT', $yourBlobUrl, $binaryData, [
    'Content-Type' => 'application/octet-stream'
]);

3. 从其他来源获取的流

如果是从其他接口或者服务拿到的流资源,也可以直接传入,比如:

// 从另一个请求获取的响应流
$remoteStream = $anotherClient->request('GET', $remoteFileUrl)->toStream();
$response = sendRequest($client, 'PUT', $yourBlobUrl, $remoteStream);

注意点

  • 如果你上传的是特定类型的文件(比如图片、视频),记得把Content-Type改成对应的类型(比如image/pngvideo/mp4),而不是默认的application/octet-stream
  • 流式上传时,timeout要设置足够长,避免大文件上传超时
  • 如果你需要监控上传进度,Symfony HTTP Client也支持通过on_progress回调来实现,不过这个属于进阶需求了,有需要的话可以再研究

备注:内容来源于stack exchange,提问作者Simao Gomes Viana

火山引擎 最新活动