Guzzle 6下载文件

16

需要使用Guzzle 6从Rest API下载文件,但不想将文件保存在本地而是从Web浏览器下载。目前的代码如下,但我认为漏掉了某些东西?

    <?php

//code for Guzzle etc removed

$responsesfile = $client->request('GET', 'documents/1234/content', 
        [
        'headers' => [
            'Cache-Control' => 'no-cache', 
            'Content-Type' => 'application/pdf',
            'Content-Type' => 'Content-Disposition: attachment; filename="test"'
        ]
        ]


    );
    return $responsesfile;
    ?>
4个回答

45

仅仅在Guzzle文档中进行研究,例如这里

传递一个字符串来指定存储响应正文内容的文件路径:

$client->request('GET', '/stream/20', ['sink' => '/path/to/file']);

将从fopen()返回的资源传递给write函数,以将响应写入PHP流:

$resource = fopen('/path/to/file', 'w');
$client->request('GET', '/stream/20', ['sink' => $resource]);
将一个Psr\Http\Message\StreamInterface对象传递给流式传输响应主体到已打开的PSR-7流。
$resource = fopen('/path/to/file', 'w');
$stream = GuzzleHttp\Psr7\stream_for($resource);
$client->request('GET', '/stream/20', ['save_to' => $stream]);

好的回答,帮助我找到了流解决方案。谢谢! - Kevin Lindmark
2
好的回答,我只想指出,如果您不将响应存储到本地变量中,它会超出范围并在您处理它之前关闭资源。 - Vody
1
真的需要将响应保存到磁盘上吗?我不能直接将响应返回给客户端而不保存它吗? - Ionel Lupu

6

stream_for 在版本7.2中已被弃用。您可以使用 GuzzleHttp\Psr7\Utils::streamFor($resource) 代替。


0
首先,当你发送一些东西(POST/PUT)时,Content-Type头才有意义,但对于GET请求则没有。
其次,您的问题是什么? Guzzle默认不会将响应主体(文件)存储在某个地方,因此您可以在应用程序内部处理它,例如$responsesfile->getBody()

0
如果源API的响应返回的实际文件包含适当的标头,您可以在不保存文件的情况下将其返回以供下载。
只需重用响应中的标头并返回响应正文。浏览器将识别返回的响应是用于文件下载的。
这可能取决于实际的PHP框架以及它如何处理HTTP响应,但通常您可以在原始PHP中执行类似以下的操作(请注意,$downloadResponse是从GuzzleHttp的get()方法返回的):
//** @var Psr\Http\Message\ResponseInterface $downloadResponse    
foreach ($downloadResponse->getHeaders() as $headerName => $headerValues) {
    header("$headerName:" . implode(',', $headerValues));
}
echo $downloadResponse->getBody();

请注意,上面的示例中我没有处理简单合并标头值可能引起问题的特殊情况(例如,Set-Cookie 值)。
为了更好地理解,我还添加了一个正确设置标头的示例,结合所提供的代码将导致实际的文件下载。
Date: Mon, 11 Sep 2023 15:22:41 GMT
Content-Type: application/pdf
Content-Length: 6850
Connection: keep-alive
Vary: Origin
Access-Control-Allow-Credentials: true
access-control-allow-origin: *
Content-Disposition: attachment; filename="sample.pdf"
ETag: W/"1ac2-W5cdxxx7R45QxxxnBvKO+R7asd-abc"
Strict-Transport-Security: max-age=15724800; includeSubDomains

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接