I'm still on the learning slopes with Guzzle, but am stumped with this issue...
I'm trying to retrieve an audio file from a 3rd party API using Guzzle. I've written a class with a number of functions and they all work apart from the very last stage of the 'download' function - the browser does not prompt to save the audio file
Call to get audio file, using AJAX
$callRows.on("click", ".download", function() {
const $this = $(this);
$this.parent().hide().next().show();
$.ajax({
type : "POST",
url : "submgmt",
data : {
task : "getMedia",
target : $this.data("id")
},
success : function(data) {
$this.parent().show().next().hide();
},
error : function (XMLHttpRequest, textStatus, errorThrown) {
$dialog.attr("title", textStatus);
$dialog.html("<br>" + errorThrown + "<br><br><h4>Click OK to continue</h4>");
$dialog.dialog({
buttons : {
"OK" : function () {
$dialog.dialog("destroy");
}
},
dialogClass : "no-close",
modal : true,
resizable : false
});
$this.parent().show().next().hide();
}
});
});
FIRST TRY Function to call download function
$ucCall = new ucCalls($ucAuth);
try {
$response = $ucCall->getMedia($target);
if ($response['code']===404) {
$result['ERROR'] = "1";
$result['DETAILS'] = "File is no longer available";
echo json_encode($result);
exit();
} else {
header("Date: " . $response['headers']['Date'][0]);
header("Cache-Control: " . $response['headers']['Cache-Control'][0]);
header("Pragma: " . $response['headers']['Pragma'][0]);
header("Expires: " . $response['headers']['Expires'][0]);
header("Content-Type: " . $response['headers']['Content-Type'][0]);
header('Content-Disposition: attachment; filename="' . basename($response['filename']) . '"');
header("Content-Length: " . filesize($response['filename']));
ob_clean();
flush();
readfile($response['filename']);
exit;
}
} catch (Exception $e) {
$result['ERROR'] = "1";
$result['DETAILS'] = $e->getCode() . " - " . $e->getMessage();
echo json_encode($result);
exit();
}
Class to retrieve audio files from 3rd party API
class ucCalls {
private Client $client;
public function __construct($authString)
{
$this->client = new Client([
'base_uri' => 'https://url-of-host',
'timeout' => 5,
'headers' => [
'Authorization' => 'Basic ' . $authString,
'Accept' => 'application/json'
],
]);
}
/**
* Retrieves the unencrypted MP3 media for a (completed) recording
* @param string $id
* @return array
* @throws Exception
*/
public function getMedia(string $id): array
{
try {
$temp_file = sys_get_temp_dir() . "\uc" . make_id(6) . ".mp3";
$resource = Utils::tryFopen($temp_file, 'w');
$response = $this->client->request('GET','fw/path/to/audio/file/store/' . $id . '/Media', ['sink' => $resource]);
return [
'code' => $response->getStatusCode(),
'headers' => $response->getHeaders(),
'filename' => $temp_file
];
} catch (ConnectException $e) {
error_log(print_r("## EXCEPTION ## ucCalls (getMedia) - ConnectException -> " . $e->getMessage(),true));
throw new Exception ("Connection Error",500);
} catch (ServerException|ClientException $e) {
error_log(print_r("## EXCEPTION ## ucCalls (getMedia) - ServerException|ClientException -> " . $e->getMessage(),true));
throw new Exception ($e->getResponse()->getReasonPhrase(),$e->getResponse()->getStatusCode());
} catch (GuzzleException $e) {
error_log(print_r("## EXCEPTION ## ucCalls (getMedia) - GuzzleException -> " . $e->getMessage(),true));
throw new Exception ("Unhandled Exception",400);
}
}
}
SECOND TRY was to try using the Guzzle Stream
Function to call download function
$ucCall = new ucCalls($ucAuth);
try {
$ucCall->getMedia($target);
} catch (Exception $e) {
$result['ERROR'] = "1";
$result['DETAILS'] = $e->getCode() . " - " . $e->getMessage();
echo json_encode($result);
exit();
}
Class
public function getMedia(string $id)
{
try {
$temp_file = sys_get_temp_dir() . "\uc" . make_id(6) . ".mp3";
$resource = Utils::tryFopen($temp_file, 'w+');
$stream = Utils::streamFor($resource);
$this->client->request('GET','fw/path/to/audio/file/store/' . $id . '/Media', ['sink' => $stream]);
header("Cache-Control: no-cache");
header("Content-Type: audio/mp3");
header('Content-Disposition: attachment; filename="' . basename($stream->getMetadata('uri')) . '"');
header('Content-Length: ' . filesize($stream->getMetadata('uri')));
echo $stream;
} catch (ConnectException $e) {
error_log(print_r("## EXCEPTION ## ucCalls (getMedia) - ConnectException -> " . $e->getMessage(),true));
throw new Exception ("Connection Error",500);
} catch (ServerException|ClientException $e) {
error_log(print_r("## EXCEPTION ## ucCalls (getMedia) - ServerException|ClientException -> " . $e->getMessage(),true));
throw new Exception ($e->getResponse()->getReasonPhrase(),$e->getResponse()->getStatusCode());
} catch (GuzzleException $e) {
error_log(print_r("## EXCEPTION ## ucCalls (getMedia) - GuzzleException -> " . $e->getMessage(),true));
throw new Exception ("Unhandled Exception",400);
}
}
Both these functions create the audio file in a temp store on my local web server, so the audio file retrieval from the 3rd party works. This is where I get stumped...
The file appears to transfer to the client, the header attributes are recognised and the correct amount of data is transfer (filesize) - but the client browser (tested in Edge and Firefox) is not prompting to save the file. Just getting an encoded string, as per the screenshots...
Any thoughts or guidance would be appreciated...
Once you get the encoded response you can check it whether it is base64 encoded or not or use base64_encode($content)
provided by php.
$encoded_response = 'your encoded string';
$base64 = base64_encode($encoded_response);
$mime = "audio/mpeg";
$img = ('data:' . $mime . ';base64,' . $base64); // would be like data:audio/mpeg;base64,YxAAEaAIEeUAQAgBgNg...
<audio autoplay controls src="data:audio/mpeg;base64,YxAAEaAIEeUAQAgBgNg...">
The “audio” tag is not supported by your browser.
</audio>
How we can insert header and footer in google docs with google docs api using PHP code
Writing a new and appending a file in PHP without erasing contents
How to combine 2 arrays with the condition that 2 and 5 values will be from the second array?
How to keep the ?error on url if page extension not included?
I want to curl a HLS that returns forbidden in the browser with Php so in another words i want to return the contents of say
I have 4 tables : users , user_store_info , user_store_options , product_supplies
i have a datajson file like this in which i am getting a list of data i want to add another parameter{p_quantity} to this json file
I have an activity with three MenuItem'sI have three variables at the top of the activity class for each MenuItem (e