Guzzle 6 download file - php

Need help using Guzzle 6 for downloading a file from a rest API. I don't want the file to be saved locally but downloaded from web browser. Code so far below, but believe I am missing something?
<?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;
?>

Just do research inside Guzzle's docs, for example here
Pass a string to specify the path to a file that will store the contents of the response body:
$client->request('GET', '/stream/20', ['sink' => '/path/to/file']);
Pass a resource returned from fopen() to write the response to a PHP stream:
$resource = fopen('/path/to/file', 'w');
$client->request('GET', '/stream/20', ['sink' => $resource]);
Pass a Psr\Http\Message\StreamInterface object to stream the response body to an open PSR-7 stream.
$resource = fopen('/path/to/file', 'w');
$stream = GuzzleHttp\Psr7\stream_for($resource);
$client->request('GET', '/stream/20', ['save_to' => $stream]);

stream_for is deprecated in version 7.2. You can use
GuzzleHttp\Psr7\Utils::streamFor($resource) instead.

First of all, Content-Type header only makes sense when you send something (POST/PUT), but not for GET requests.
Secondly, what is your issue? Guzzle by default does not store the response body (file) somewhere, so you can work with it inside your app, like $responsesfile->getBody().

Related

Download File With Guzzle

I'm attempting to retrieve a file attachment with Guzzle. The file isn't available directly through an endpoint, but the download is initiated via the end point and downloaded to my browser. Can I retrieve this file with Guzzle?
I successfully login to the site, but what is saved to my file is the html of the site not the download. The file contents seems to come through when I make the request with insomnia rest client, but not with Guzzle.
$client = new GuzzleHttp\Client();
$cookieJar = new \GuzzleHttp\Cookie\CookieJar();
$response = $client->post('https://test.com/login', [
'form_params' => [
'username' => $username,
'password' => $password,
'action' => 'login'
],
'cookies' => $cookieJar
]);
$resource = fopen(__DIR__.'/../../feeds/test.xls', 'w');
$stream = GuzzleHttp\Psr7\stream_for($resource);
$response = $client->request('GET', 'https://test.com/download', ['sink' => $stream]);
If you want to perform an authentication step and then a download step, you'll need to make sure the cookies are persisted across both requests. Right now you're only passing your $cookieJar variable to the first one.
The explicit way of doing this would be to add it to the options for the second request:
['sink' => $stream, 'cookies' => $cookieJar]
but it might be easier to take advantage of the option in the client constructor itself:
$client = new GuzzleHttp\Client(['cookies' => true);
That means that every request (with that client) will automatically use a shared cookie jar, and you don't need to worry about passing it into each request separately.
You should send Content-Disposition header in order to specify that the client should receive file downloading as a response. According to your GET HTTP request which will capture the contents into the $stream resource, finally you can output these contents to browser with stream_get_contents.
<?php
// your 3rd party end-point authentication
...
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="test.xls"');
$resource = fopen(__DIR__.'/../../feeds/test.xls', 'w');
$stream = GuzzleHttp\Psr7\stream_for($resource);
$response = $client->request('GET', 'https://test.com/download', ['sink' => $stream]);
echo stream_get_contents($stream);

forcing guzzle to download the zip files

Need help downloading the the json response zip files.
I am using guzzle json response from the remote server which returns filenames and modification dates to me. i want to download all these zip files to my storage folder of local server..
so it would work like this
remote server gives json response filenames
i take the filenames and create my link and force guzzle to download those files to my local server.
Here is my code
ini_set('max_execution_time', '0');
$url = "https://feeds.example.com/zips/publisher/";
try
{
$client = new GuzzleHttp\Client();
$res = $client->request('GET', $url, [
'auth' => ['username', 'password'],
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json'
],
]);
$responses = json_decode($res->getBody()->getContents());
foreach ($responses->incrementalFeed as $feed)
{
$downloadLink = $url . $feed->name;
$client->get($downloadLink, ['auth' => ['username', 'password']]);
Storage::put($feed->name, $downloadLink);
}
}
catch (ClientException $e) {
echo $e->getMessage();
}
it downloads all the zip files to my storage folder but all the file are like 1kb , empty .. however in remote website those files are like from 10mb to 600mbs
what am i doing wrong here?
You’re not downloading anything.
You need to use guzzle again to download the files
e.g
$response = $client->get($downloadLink);
Storage::put($feed->name, $response->getBody());

guzzle getbody function accessing the diffrenet elements of response

i am using guzzle to post some data to some api and recive some data back here is my code :
$response = $client->request('POST', 'http://url/api/v1/transaction/Verify', [
'headers' => ['Content-Type' => 'application/json'],
'body' => '{
"tn":"1905463527",
}'
]);
$responebody = $response->getBody();
i exacly dont know if i am getting string or object when ever i use getbody of guzzle but here is what i get when i echo the response :
{"errorCode":null,"errorMessage":"Canceled by user.","succeed":false,"tn":1905463527,"verifyCount":35,"amount":10000}
now here for example i want to access the "succeed " element and i want to know how can i access to check if it is true or not ,
You should check the Content-Type header and if it's application/json you can run json_decode on the body. Take this as an example
if ($response->getContentType() == 'application/json') {
$responseBody = json_decode($response->getContent());
// now you can access $responseBody->succeed
...
}

Send Body as raw using Guzzle

I am trying to use Guzzle to send POST request to my web service. this service accepts body as raw. It works fine when I use postman but I doesn't using Guzzle. when using Guzzle, I get only the webservice description as I put the web service URL in the browser.
here is my code:
$body = "CA::Read:PackageItems (CustomerId='xxxxxx',AllPackages=TRUE);";
$headers = [
....
....
];
$client = new Client();
$response = $client->request('POST', 'http://172.19.34.67:9882/TisService',$headers,$body);
echo $body = $response->getBody();
seems headers or body doesn't pass through.
Try like this
$response = $client->request('POST', 'http://172.19.34.67:9882/TisService',['headers' => $headers, 'body' => $body]);
I have recently had to implement Guzzle for the first time and it is a fairly simple library to use.
First I created a new Client
// Passed in our options with just our base_uri in
$client = new Client(["base_uri" => "http://example.com"]);
I then created a POST request, not how I am using new Request instead of $client->request(... though. This doesn't really matter to much that I've used new Request though.
// Create a simple request object of type 'POST' with our remaining URI
// our headers and the body of our request.
$request = new Request('POST', '/api/v1/user/', $this->_headers, $this->body);
so in essence it would look like:
$request = new Request('POST', '/api/v1/user/', ['Content-Type' => "application/json, 'Accept' => "application/json"], '{"username": "myuser"}');
$this->headers is a simple key-value pair array of our request headers making sure to set the Content-Type header and $this->body is a simple string object, in my case it forms a JSON body.
I can simply then just call the $client->send(... method to send the request like:
// send would return us our ResponseInterface object as long as an exception wasn't thrown.
$rawResponse = $client->send($request, $this->_options);
$this->_options is a simple key-value pair array again simple to the headers array but this includes things like timeout for the request.
For me I have created a simple Factory object called HttpClient that constructs the whole Guzzle request for me this is why I just create a new Request object instead of calling $client->request(... which will also send the request.
What you essentially need to do to send data as raw is to json_encode an array of your $data and send it in the request body.
$request = new Request(
'POST',
$url,
['Content-Type' => 'application/json', 'Accept' => 'application/json'],
\GuzzleHttp\json_encode($data)
);
$response = $client->send($request);
$content = $response->getBody()->getContents();
Using guzzle Request GuzzleHttp\Psr7\Request; and Client GuzzleHttp\Client

Specify raw body of a POST request with Guzzle

With Guzzle (version 3), I'd like to specify the body of a POST request in "raw" mode. I'm currently trying this:
$guzzleRequest = $client->createRequest(
'POST',
$uri,
null,
'un=one&deux=two'
);
But it kind of doesn't work. If I dump my $guzzleRequest I can see that postFields->data is empty. Using $guzzleRequest->setBody() afterwards doesn't help.
However if I specify the body as ['un'=>'one', 'deux'=>'two'], it works as expected.
How can I specify the body of the request as 'un=one&deux=two'?
First I would highly recommend that you upgrade to Guzzle 6 as Guzzle 3 is deprecated and EOL.
It has been a long time since I used Guzzle 3 but I do believe you want the following:
$request = $client->post(
$uri,
$header = [],
$params = [
'un' => 'one',
'deux' => 'two',
]);
$response = $request->send();
Guzzle will automatically set the Content-Type header.
More information is available with the Post Request Documentation.
In response to your comment:
$request = $client->post(
$uri,
$headers = ['Content-Type' => 'application/x-www-form-urlencoded'],
EntityBody::fromString($urlencodedstring)
)
For this, reference: EntityBody Source and RequestFactory::create()

Categories