我正在使用的远程服务返回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文件,因此我可以将链接提供给用户,而无需将整个文件加载到内存中。这里的问题是文件很大(在base64中50mb PDF如此之大)。
这很好,直到远程服务器决定添加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响应的主体上添加流过滤器?
答案 0 :(得分:0)
为了做到这一点,我必须从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()
的任何后续使用都不会执行任何操作。这可能不太理想,但我不知道是否还有其他办法解决这个问题。