【问题标题】:Add a conversion filter to guzzle response为 guzzle 响应添加转换过滤器
【发布时间】:2017-07-14 17:21:30
【问题描述】:

我正在使用一个远程服务,它返回一个 base64 编码的 PDF。我是这样使用的:

$fp = fopen($url, "r");
$fn = md5($url).".pdf";
stream_filter_append($fp, 'convert.base64-decode');
\Storage::drive("public")->put($fn,$fp);
return response()->json(["url"=>\Storage::drive("public")->url($fn)]);

这用于在公共磁盘上下载和写入 PDF 文件,这样我就可以向用户提供指向它的链接,而无需将整个文件加载到内存中。这里的问题是文件很大(50mb PDF 在base64 中更大)。

在远程服务器决定添加 fopen 无法处理的内部重定向之前,这一切正常。 我决定将我的代码转换为使用 Guzzle,而不是编写自己的解决方案来处理内部重定向。

这是我尝试过的:

$client = new Client();
$res = $client->request("GET", $url);
$fp = $res->getBody();
$fn = md5($url).".pdf";
stream_filter_append($fp, 'convert.base64-decode'); //Works without this
\Storage::drive("public")->put($fn,$fp);
return response()->json(["url"=>\Storage::drive("public")->url($fn)]);

问题是stream_filter_append,没有它代码可以正常工作。我得到的错误是

stream_filter_append() 期望参数 1 是资源,给定对象

有没有办法在 guzzle 响应的主体上附加流过滤器?

【问题讨论】:

    标签: php laravel laravel-5 guzzle


    【解决方案1】:

    为了做到这一点,我必须从 guzzle 流中获取底层资源。显然 Guzzle 很乐意提供这个,这是我的代码:

    $client = new Client();
    $res = $client->request("GET", $url);
    $fp = $res->getBody()->dettach(); //The magic method.
    $fn = md5($url).".pdf";
    stream_filter_append($fp, 'convert.base64-decode'); //Works without this
    \Storage::drive("public")->put($fn,$fp);
    return response()->json(["url"=>\Storage::drive("public")->url($fn)]);
    

    注意:dettach 方法执行名称所暗示的操作并将流与 Guzzle 分离,因此任何后续使用 $res->getBody()->read() 都不会做任何事情。这可能并不理想,但我不知道是否有其他解决方法。

    【讨论】:

      猜你喜欢
      • 2012-07-07
      • 2015-12-26
      • 1970-01-01
      • 1970-01-01
      • 2016-08-10
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 2021-12-22
      相关资源
      最近更新 更多