How do I fetch a resource from AWS S3 in PHP? - php

The AWS S3 documentation is quite clear and straightforward:
<?php
// Include the AWS SDK using the Composer autoloader.
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';
// Instantiate the client.
$s3 = S3Client::factory();
try {
// Get the object
$result = $s3->getObject(array(
'Bucket' => $bucket,
'Key' => $keyname
));
// Display the object in the browser
header("Content-Type: {$result['ContentType']}");
echo $result['Body'];
} catch (S3Exception $e) {
echo $e->getMessage() . "\n";
}
This strongly suggests that $result['Body'] is the actual content of the file (in my case, a JSON document). However, if I do print_r($result['Body']) I get a Guzzle Object:
Guzzle\Http\EntityBody Object
(
[contentEncoding:protected] =>
[rewindFunction:protected] =>
[stream:protected] => Resource id #9
[size:protected] =>
[cache:protected] => Array
(
[wrapper_type] => PHP
[stream_type] => TEMP
[mode] => w+b
[unread_bytes] => 0
[seekable] => 1
[uri] => php://temp
[is_local] => 1
[is_readable] => 1
[is_writable] => 1
)
[customData:protected] => Array
(
[default] => 1
)
)
How can I retrieve the actual content of the file?
composer.json
{
"require": {
"aws/aws-sdk-php": "2.*",
"guzzle/guzzle": "3.9.3",
}
}

Guzzle EntityBody classes can just be cast to a string to fetch the actual response, so in your case
$response = (string) $result['Body'];
For a bit of clarity — the reason the example works is that when calling echo, the following variable (or statement) is automatically cast to a string. When calling print_r instead, you get a more detailed view of the object, which may or may not include the string you're looking for.

Related

Delete a single file from AWS s3 bucket?

I am trying to delete a single file from AWS s3 bucket and my code is as below:
$removeUploadedDocFromTestingFolder = array(
"removeFromTestFolder" =>
array(
"bucket" => "my-bucket"
),
"AccessKeys" =>
array(
"access_key" => "my access key",
"seceret_key" => "my secret key"
)
);
$_SERVER['HOME'] = DIR_HOME;
ini_set('display_errors',1); error_reporting(E_ALL);
use Aws\S3\S3Client;
use Aws\Common\Credentials\Credentials;
$client = S3Client::factory();
//$objError = new ErrorReporting();
$bucket = $removeUploadedDocFromTestingFolder['removeFromTestFolder']['bucket'];
//testing file setup on local server....
$file1 = "my-file";
//File reference on cloud.....Object URL
$file1_cloud = "https://Object URL/myFile/myFile";
echo "here 0";
$client->deleteObject($bucket, $file1_cloud);
Can anyone tell what I am doing wrong that the code is not deleting the file.
I tried the following code but it didn't work:
try {
//$client->deleteObject($bucket, $file1_cloud);
$result = $client->deleteObject(['Bucket' => 'my-bucket','Key' => 'myFile.png']);
} catch(\Aws\S3\Exception\S3Exception $e) {
echo "error"+$e;
}
Thanks
The object is not being deleted because you have asked S3 to delete a non-existent object, and S3 treats this as a no-op rather than an error. This is because you have indicated a URL rather than the key of the object.
An example of an S3 object key is:
testing/cats/fluffykins.png
Note that it's not a URL and it doesn't begin with forward slash.
An example of the correct way to call the PHP deleteObject function is:
$result = $s3Client->deleteObject([
'Bucket' => $bucket,
'Key' => $key,
]);
Note that it takes an array of parameters, including bucket and key. It assumes PHP 5.4 or later in which you can use the short array syntax, which replaces array() with [].
I've resolved the issue by using the following code:
$client = S3Client::factory(array(
'key' => "mykey",
'secret' => "my secret key"
));
//File reference on cloud.....
$file1_cloud = "TestFile/myFile.png";
$result = $client->deleteObject(array(
'Bucket' => $bucket,
'Key' => 'TestFile/myFile.png'));

AWS s3Client->copyObject succeeds but the copied object loses is garbled

Please assist.
I am successfully uploading objects to S3 using the following code snippet:
// Send a PutObject request and get the result object.
$result = $this->s3EncryptionClient->putObject([
'#MaterialsProvider' => $this->materialsProvider,
'#CipherOptions' => $this->cipherOptions,
'Bucket' => $this->s3BucketName,
'Key' => $key,
'ContentType' => $mimeType,
'ContentLength' => filesize($filePath),
'ContentDisposition' => "attachment; filename='" . $fileName . "'",
'Body' => fopen($filePath ,'r')
]);
And I can successfully download the object using the following snippet:
// Download the contents of the object.
$result = $this->s3EncryptionClient->getObject([
'#MaterialsProvider' => $this->materialsProvider,
'#CipherOptions' => $this->cipherOptions,
'Bucket' => $this->s3BucketName,
'Key' => $key
]);
The problem comes in when i try copy the object using the following code snippet:
$result = $this->s3Client->CopyObject([
'Bucket' => $this->s3BucketName,
'CopySource' => $CopySource,
'Key' => $dstKey,
]);
The object seems to be copied incorrectly and when i try download the new object using the download code i pasted earlier in this post, The object is not found and an AWSException
resulted in a 404 Not Found response
Any idea how I can resolve the issue?

Google cloud -speech api return null result

I work with Google cloud speech API. When I run my script there is a call to the API and a response. The operation info returns data, but the result is empty.
Here is my code (where file url, file name, key url, project name and bucket name I deleted the real data):
function __construct(){
$file_url='file path.mp3';
$filename='file name.mp3';
/** Create google client **/
$client = new Google_Client();
$key='path to google key';
putenv($key);
$client->useApplicationDefaultCredentials();
/** Create storage **/
$str_config = array(
'projectId' => 'project id'
);
$storage = new StorageClient($str_config);
$bucket_name='bucket name';
$bucket=$storage->bucket($bucket_name);
$object = $bucket->object($filename);
/** Create Speech **/
$config = array(
'projectId' => 'project id',
'languageCode' => 'en-US'
);
$options = array(
"encoding"=>'LINEAR16',
"languageCode"=>"en-US",
'sampleRateHertz' => 16000
)
;
$speech = new Google\Cloud\Speech\SpeechClient($config);
$operation = $speech->beginRecognizeOperation(
$object,
$options
);
$backoff = new ExponentialBackoff(100);
$backoff->execute(function () use ($operation) {
print('Waiting for operation to complete' . PHP_EOL);
$operation->reload();
if (!$operation->isComplete()) {
throw new Exception('Job has not yet completed', 500);
}
});
if ($operation->isComplete()) {
if (empty($results = $operation->results())) {
$results = $operation->info();
}
var_dump($results, $operatimon->results());
}
}
The result i get call:
Array
(
[0] => Array
(
[name] => some name
[metadata] => Array
(
[#type]=> type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeMetadata
[progressPercent] => 100
[startTime] => 2017-07-16T19:15:58.768490Z
[lastUpdateTime] => 2017-07-16T19:15:59.999625Z
)
[done] => 1
[response] => Array
(
[#type]=> type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeResponse
[totalBilledTime] => 15s
)
)
[1] => Array
(
)
)
I tried several file type whit several encodings, can't find the right combination. Or maybe there is another problem. Pleas Help.
Solved it by using the ffmpeg library to encode the audio to flac whit mono channel.
For anyone else encountering this problem, the issue could lie in your audio file not matching the encoding you've entered in your option array.
Check this resource:
https://cloud.google.com/speech-to-text/docs/reference/rest/v1beta1/RecognitionConfig#AudioEncoding
Just like the accepted answer, by changing from "LINEAR16" to "FLAC" and converting my audio file to FLAC, it worked for me.

AWS: Can't retrieve keys in S3

I need to grab the contents on one of my buckets. I try to do this using the AWS PHP SDK, but nothing is returned. Here's my code:
use Aws\S3\S3Client;
$s3client = S3Client::factory(array('credentials' => array(
'key' => '???????',
'secret' => '???????' ), 'region' => '?????', 'version' => 'latest', ));
try {
$data = $s3client->getIterator('ListObjects', array("Bucket" => "?????"));
print_r($data);
} catch (S3Exception $e) {
echo $e->getMessage() . "\n";
}
Here's the ouput:
Generator Object ( )
The output I get from that code is showing there's nothing wrong. However, there should be some content. The credentials I use are the same ones I use for uploading objects to the bucket, so I don't think those are bad. Am I missing something? How do I retrieve my buckets keys?
you are getting the iterator and not the objects.
To get to the objects you need to use the iterator. Something like:
foreach ($data as $object) {
echo $object['Key'] . "\n";
}

Using s3 server-side encryption with PHP

I have decide to avail of amazons new server-side encryption with s3, however, I have run into a problem which I am unable to resolve.
I am using the s3 PHP class found here : https://github.com/tpyo/amazon-s3-php-class
I had been using this code to put objects originally (and it was working) :
S3::putObjectFile($file, $s3_bucket_name, $file_path, S3::ACL_PRIVATE,
array(),
array(
"Content-Disposition" => "attachment; filename=$filename",
"Content-Type" => "application/octet-stream"
)
);
I then did as instructed here : http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTObjectPUT.html and added the 'x-amz-server-side​-encryption' request header. But now when I try to put an object it fails without error.
My new code is :
S3::putObjectFile($file, $s3_bucket_name, $file_path, S3::ACL_PRIVATE,
array(),
array(
"Content-Disposition" => "attachment; filename=$filename",
"Content-Type" => "application/octet-stream",
"x-amz-server-side​-encryption" => "AES256"
)
);
Has anybody experimented with this new feature or can anyone see an error in the code.
Cheers.
That header should be part of the $metaHeaders array and not $requestHeaders array.
S3::putObjectFile($file, $s3_bucket_name, $file_path, S3::ACL_PRIVATE,
array(
"x-amz-server-side​-encryption" => "AES256"
),
array(
"Content-Disposition" => "attachment; filename=$filename",
"Content-Type" => "application/octet-stream"
)
);
Here's the method definition from the docs:
putObject (mixed $input,
string $bucket,
string $uri,
[constant $acl = S3::ACL_PRIVATE],
[array $metaHeaders = array()],
[array $requestHeaders = array()])
You might also consider using the SDK for PHP?
We can upload files with encryption using the code following
$s3->create_object($bucket_name,$destination,array(
'acl'=>AmazonS3::ACL_PUBLIC,
'fileUpload' => $file_local,
'encryption'=>"AES256"));
And you can download latest sdk from here
With the official SDK:
use Aws\S3\S3Client;
$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';
// $filepath should be absolute path to a file on disk
$filepath = '*** Your File Path ***';
// Instantiate the client.
$s3 = S3Client::factory();
// Upload a file with server-side encryption.
$result = $s3->putObject(array(
'Bucket' => $bucket,
'Key' => $keyname,
'SourceFile' => $filepath,
'ServerSideEncryption' => 'AES256',
));
Changing Server-Side Encryption of an Existing Object (Copy Operation)
use Aws\S3\S3Client;
$sourceBucket = '*** Your Source Bucket Name ***';
$sourceKeyname = '*** Your Source Object Key ***';
$targetBucket = '*** Your Target Bucket Name ***';
$targetKeyname = '*** Your Target Object Key ***';
// Instantiate the client.
$s3 = S3Client::factory();
// Copy an object and add server-side encryption.
$result = $s3->copyObject(array(
'Bucket' => $targetBucket,
'Key' => $targetKeyname,
'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
'ServerSideEncryption' => 'AES256',
));
Source: http://docs.aws.amazon.com/AmazonS3/latest/dev/SSEUsingPHPSDK.html
With laravel 5+ it can be done easily through filesystems.php config, you don't need to get driver or low level object.
's3' => [
'driver' => 's3',
'key' => "Your Key",
'secret' => "Your Secret",
'region' => "Bucket Region",
'bucket' => "Bucket Name",
'options' => [
'ServerSideEncryption' => 'AES256',
]
],
//Code
$disk->put("filename", "content", "public"); // will have AES for file

Categories