Amazon S3: Uncaught Error: Class 'S3Client' not found - php

I'm trying to upload a .zip file to the Amazon S3 service but I keep getting the error:
Uncaught Error: Class 'S3Client' not found in /class/database.class.php:411
This is the basis of the code. I have the exit() from trying to debug. The class_exists function specifis that the S3Client exists and echo's "Class!!!" to the page.
I added an echo statement in the amazon autoload file and it echo's that so it is finding the autoload files.
Why can't PHP find the class when trying to call it?
My Amazon Class
require_once( $path["full"].'/assets/vendor/amazon-s3/aws-autoloader.php' );
use Aws\S3\S3Client;
class amazons3 {
// For future use to build some functions to help.
}
My-Autoload
//Misc Functions Above
include('/path/to/amazon-s3.class.php')
//Misc Functions Below
Inside Back-up Database Function
include('/path/to/my/my-autoload.class.php');
if(class_exists('Aws\S3\S3Client')) {
echo "CLASS!!!";
/* Line 411 */ $s3 = new S3Client([
'version' => 'latest',
'region' => 'us-west-2'
]);
}
else {
echo "No Class";
}
exit(0);
try {
$s3->putObject([
'Bucket' => $data["domain"],
'Key' => 'my-object',
'Body' => fopen($zipName, 'r'),
'ACL' => 'public-read',
]);
} catch (Aws\S3\Exception\S3Exception $e) {
echo "There was an error uploading the file.\n";
}
Update
I am not using composer; I downloaded the package and uploaded it to my server.
I've still had no luck with getting this to recognize the S3Client class. I added an echo to the top of the S3Client.php right above the class that is in the amazon package to see if it is included and it is and echoed out the string on my page, so from everything I know, all Amazon class files are included.
Update 2
I added the include files to the include of the Amazon autoloader.

In your class_exists call, you specify the fully-qualified class name (with its namespace):
if(class_exists('Aws\S3\S3Client')) {
echo "CLASS!!!";
}
But when you try to instantiate it, you use just the class name:
/* Line 411 */ $s3 = new S3Client([
'version' => 'latest',
'region' => 'us-west-2'
]);
Note that the error message doesn't include the namespace Aws\S3, because PHP doesn't know that S3Client should actually mean Aws\S3\S3Client.
If you instantiate the class with its fully-qualified name it will work:
/* Line 411 */ $s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-west-2'
]);
For the name S3Client to expand to Aws\S3\S3Client, your code needs to either a) be inside the Aws\S3 namespace; or b) have an appropriate use statement at the top of the file.
The important thing to remember is that namespace and use statements only affect the current file, they can't be loaded via a require/include.
So this will also work:
/* top of file */
use Aws\S3\S3Client;
// ...
/* Line 411 */ $s3 = new S3Client([
'version' => 'latest',
'region' => 'us-west-2'
]);
The name you use for the class can be different in every file, with use ... as, so you can also do this:
/* top of file */
use Aws\S3\S3Client as AmazonS3;
use Something\Else as S3Client;
// ...
/* Line 411 */ $s3 = new AmazonS3([
'version' => 'latest',
'region' => 'us-west-2'
]);
To see what PHP resolves a bare class name to in a particular file, you can use the magic ::class suffix, which just expands the name according to current namespace and use rules (even if there isn't actually a class with that name):
if ( class_exists(S3Client::class) ) {
echo 'Class exists: ' . S3Client::class;
}
else {
echo 'Class does not exist: ' . S3Client::class;
}
This is almost always what you want to do when you want a fully-qualified class name in a string.

Related

Class S3 not found if use inside function

I am new in PHP. I am trying to make S3 upload function so I can use it in my other php files. I have made s3.php file like this
<?php
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
use Aws\S3\ObjectUploader;
use Aws\S3\MultipartUploader;
use Aws\Exception\MultipartUploadException;
function bucket_upload($BUCKET_ACCESS_KEY,$BUCKET_SECRET_KEY,$BUCKET_REGION,$BUCKET_URL,$BUCKET_NAME,$FILE,$FILE_NAME){
require __DIR__.'/vendor/autoload.php';
$config = [
'credentials' => new \Aws\Credentials\Credentials(
$BUCKET_ACCESS_KEY,
$BUCKET_SECRET_KEY
),
'version' => 'latest',
'region' => $BUCKET_REGION,
'endpoint' => $BUCKET_URL
];
$s3Client = new \Aws\S3\S3Client($config);
if($s3Client->putObjectFile($FILE, $BUCKET_NAME, $FILE_NAME, S3::ACL_PUBLIC_READ)) {
return true;
}else{
return false;
}
}
Its working fine if I do not use S3 inside function. For now in function its giving me error on line 23 called class S3 not found. Let me know if anyone here can help me to fix the issue.
Thanks!

Download File from Amazon s3. Download succees but File Empty

I tried to download file from amazon s3 to local storage. Download success, file appear in local storage but the file is empty no content. Looks like missed something in the Code. Need your help friends. Thanks in Advance
here's the code :
<?php
namespace App\Console\Library;
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
use Storage;
class DownloadAWS
{
public function downloadFile(){
$s3_file = Storage::cloud()->url('Something.jsonl');
$s3 = Storage::disk('local')->put('Order.jsonl', $s3_file);
}
}
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';
$s3 = new S3Client([
'version' => 'latest',
'region' => 'us-east-1'
]);
try {
// Get the object.
$result = $s3->getObject([
'Bucket' => $bucket,
'Key' => $keyname
]);
// Display the object in the browser.
header("Content-Type: {$result['ContentType']}");
echo $result['Body'];
} catch (S3Exception $e) {
echo $e->getMessage() . PHP_EOL;
Currently, you are retrieving an URL to the s3 file and you are putting it in a file. Your code should currently create a file Order.jsonl containing the link to the s3 file.
What you really seem to want is getting the file and storing it locally. You can achieve this with the following code:
public function downloadFile()
{
$s3_file = Storage::cloud()->get('Something.jsonl');
$s3 = Storage::disk('local')->put('Order.jsonl', $s3_file);
}
The only difference is using get() vs. url().

How can I download a file from a subfolder in a amazon s3bucket using php?

I have vendor folder in my local.
I want to download a file from a sub folder which is inside my bucket's folder, to my computer's directory with the same name.
Let's say there is a bucket name "ABC" a folder is there inside it, is "DEF" And there is a sub folder named "XYZ" in "DEF". In which the files are present in folder "XYZ".
So, anyone can help me in resolving this?
function downloadFromS3($s3version,$s3region,$s3accesskey,$s3secret,$bucket,$directory){
$s3 = new S3Client([
'version' => $s3version,
'region' => $s3region,
'credentials' =>
array(
'key'=>$s3accesskey,
'secret' =>$s3secret
)
]);
try {
$basePath = 'downloads/';
$s3->downloadBucket($basePath . $directory, $bucket, $directory);
}
catch (Aws\S3\Exception\S3Exception $e) {
echo $e->getMessage();
echo "There was an error uploading the file.\n";
}
}
I am getting error like
Warning: count(): Parameter must be an array or an object that implements Countable in C:\xampp\htdocs\Performance\TestManagement\vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php on line 67
Thanks in advance..

Setting Storage class on Amazon s3 upload (ver 3)

I can't work out how to make this upload as 'reduced redundancy'
Iv added it in there twice, but it doesn't do anything. I think the way I have applied is useless.
I think i need to use this line but it seems i need to rebuild this?
setOption('StorageClass', 'REDUCED_REDUNDANCY')
require_once __DIR__ .'/vendor/autoload.php';
$options = [
'region' => $region,
'credentials' => [
'key' => $accessKeyId,
'secret' => $secretKey
],
'version' => '2006-03-01',
'signature_version' => 'v4',
'StorageClass' => 'REDUCED_REDUNDANCY',
];
$s3Client = new \Aws\S3\S3Client($options);
$uploader = new \Aws\S3\MultipartUploader($s3Client, $filename_dir , [
'bucket' => $bucket,
'key' => $filename,
'StorageClass' => 'REDUCED_REDUNDANCY',
]);
try {
$result = $uploader->upload();
echo "Upload complete: {$result['ObjectURL']}\n";
} catch (\Aws\Exception\MultipartUploadException $e) {
echo $e->getMessage() . "\n";
}
Reduced Redundancy Storage used to be about 20% lower cost, in exchange for only storing 2 copies of the data instead of 3 copies (1 redundant copy instead of 2 redundant copies).
However, with the December 2016 pricing changes to Amazon S3, it is no longer beneficial to use Reduced Redundancy Storage.
Using pricing from US Regions:
Reduced Redundancy Storage = 2.4c/GB
Standard storage = 2.3c/GB
Standard-Infrequent Access storage = 1.25c/GB + 1c/GB retrievals
Therefore, RRS is now more expensive than Standard storage. It is now cheaper to choose Standard or Standard-Infrequent Access.
Setting "StorageClass" like this won't work.
$s3Client = new \Aws\S3\S3Client($options);
Because the StorageClass is only set when the object is uploaded, you can not default all of your requests to a specific configuration during the initialization of the SDK. Each individual PUT request must have it's own options specified for it.
To use the "SetOption" line you mentioned, you may need to update your code to follow the following example found in the AWS PHP SDK Documentation.
Using the AWS PHP SDK for Multipart Upload (High-Level API) Documentation
The following PHP code sample demonstrates how to upload a file using the high-level UploadBuilder object.
<?php
// Include the AWS SDK using the Composer autoloader.
require 'vendor/autoload.php';
use Aws\Common\Exception\MultipartUploadException;
use Aws\S3\Model\MultipartUpload\UploadBuilder;
use Aws\S3\S3Client;
$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';
// Instantiate the client.
$s3 = S3Client::factory();
// Prepare the upload parameters.
$uploader = UploadBuilder::newInstance()
->setClient($s3)
->setSource('/path/to/large/file.mov')
->setBucket($bucket)
->setKey($keyname)
->setMinPartSize(25 * 1024 * 1024)
->setOption('Metadata', array(
'param1' => 'value1',
'param2' => 'value2'
))
->setOption('ACL', 'public-read')
->setConcurrency(3)
->build();
// Perform the upload. Abort the upload if something goes wrong.
try {
$uploader->upload();
echo "Upload complete.\n";
} catch (MultipartUploadException $e) {
$uploader->abort();
echo "Upload failed.\n";
echo $e->getMessage() . "\n";
}
So in this case you need to add 'StorageClass' as follows, the position isn't important, only the usage of setOption to set it:
->setOption('ACL', 'public-read')
->setOption('StorageClass', 'REDUCED_REDUNDANCY')
->setConcurrency(3)
->build();

AWS PHP SDK 2 (aws.phar) does not work with Restler Framework

I have been testing some PHP scripts that uses the aws-sdk-php to upload files to S3 storage. These scripts seems to work nicely when they are executed directly from the browser, but fails when trying to use it through an API class in Luracast Restler 3.0
A sample script that upload some dummy file is like the following:
<?php
require_once (dirname(__FILE__) . "/../lib/aws/aws.phar");
use Aws\Common\Aws;
use Aws\S3\Enum\CannedAcl;
use Aws\S3\Exception\S3Exception;
use Aws\Common\Enum\Region;
function test(){
// Instantiate an S3 client
$s3 = Aws::factory(array(
'key' => 'key',
'secret' => 'secret',
'region' => Region::EU_WEST_1
))->get('s3');
try {
$s3->putObject(array(
'Bucket' => 'my-bucket',
'Key' => '/test/test.txt',
'Body' => 'example file uploaded from php!',
'ACL' => CannedAcl::PUBLIC_READ
));
} catch (S3Exception $e) {
echo "There was an error uploading the file.\n";
}
}
This script is placed in the folder /util/test.php, while the aws-php-sdk is at /lib/aws/aws.phar
To test that this test method is well written I have created another php script at /test/upload.php with the following code:
<?php
require_once (dirname(__FILE__) . '/../util/test.php');
test();
So I can enter in the browser http://mydomain.com/test/upload.php and all is working as expected and the file is uploaded in S3 storage.
However when I call the function test() from an API class with the Restler framework, I have an error that says that Aws cannot be found:
Fatal error: Class 'Aws\Common\Aws' not found in /var/app/current/util/test.php on line 12
However the code is exactly the same that perfectly works when called from upload.php. I have been wasting hours trying to figure out what is happening here, but I cannot get any conclusion. Is like the aws-php-sdk autoloader does not work well under some circumstances.
Any hints?
This held me back quite some time,
The issue is caused by reslters autoloader which sets spl_autoload_unregiste
as described here:
https://github.com/Luracast/Restler/issues/72
One way to get arround the problem is to comment out the relevant lines in vendor/Luracast/Restler/AutoLoader.php
public static function thereCanBeOnlyOne() {
if (static::$perfectLoaders === spl_autoload_functions())
return static::$instance;
/*
if (false !== $loaders = spl_autoload_functions())
if (0 < $count = count($loaders))
for ($i = 0, static::$rogueLoaders += $loaders;
$i < $count && false != ($loader = $loaders[$i]);
$i++)
if ($loader !== static::$perfectLoaders[0])
spl_autoload_unregister($loader);
*/
return static::$instance;
}

Categories