Class S3 not found if use inside function - php

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!

Related

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

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.

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 to upload mpdf file after generating to s3 bucket in php

Can I upload mpdf file to s3 server after generating.
$file_name = $pdf->Output(time().'_'.'E-Prescription.pdf','F');
Assuming you have the AWS SDK installed in your project using composer; specifically...
composer require aws/aws-sdk-php
Yes you can, using the stream wrapper like this:
require "vendor/autoload.php";
$aws_file = 's3://bucketname/foldername/your_file_name.pdf';
//the folder is optional if you have one within your bucket
try {
$s3->registerStreamWrapper();
$mpdf->Output($aws_file, \Mpdf\Output\Destination::FILE);
}
catch (S3Exception $e) {
$data['error'] = $e->getMessage();
//show the error as a JSON callback that you can use for troubleshooting
echo json_encode($data);
exit();
}
You might have to add write permissions to your web server as follows (using Apache server on Ubuntu AWS EC2):
sudo chown -R www-data /var/www/html/vendor/mpdf/mpdf/src/Config/tmp
sudo chmod -R 755 /var/www/html/vendor/mpdf/mpdf/src/Config/tmp
Then edit the ConfigVariables.php file found at:
\vendor\mpdf\mpdf\src\Config
Change:
'tempDir' => __DIR__ . '/../../tmp',
To:
'tempDir' => __DIR__ . '/tmp',
Then create an empty folder named 'tmp' in that same directory. Then upload with joy.
// Set yours config's
define("AWS_S3_KEY", "<your_key_here>");
define("AWS_S3_SECRET", "<your_secret_here>");
define("AWS_S3_REGION", "<your_region_here example:us-east-1>");
define("AWS_S3_BUCKET", "<your_bucket_folder_name_here>");
try {
/*
doc: https://github.com/mpdf/mpdf
url/download: https://github.com/mpdf/mpdf/archive/development.zip
*/
require_once 'mpdf/mpdf.php'; // load yout mdf libe
$mpdf = new mPDF(); // set init object mPDF
$nomeArquivo = md5('cliente_01'); // set file name and cripty this
$mpdf->WriteHTML("Teste upload PDF in s3 bucket");
/*
doc: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/getting-started_installation.html
url/download: https://docs.aws.amazon.com/aws-sdk-php/v3/download/aws.zip
*/
require_once 'aws/aws-autoloader.php'; // set locate yout lib AWS
$aws_file = 's3://'.AWS_S3_BUCKET.'/'.$nomeArquivo.'.pdf';
$s3 = new Aws\S3\S3Client([
'region' => AWS_S3_REGION,
'version' => 'latest',
'credentials' => [
'key' => AWS_S3_KEY,
'secret' => AWS_S3_SECRET,
]
]);
$s3->registerStreamWrapper();
$mpdf->Output($aws_file); //Send yout mPDF File in s3-file-bucket
} catch (S3Exception $e) {
die($e->getError().' => '.$e->getMessage();
}
To do this you could use the AWS SDK for PHP.
First you will need to create a client using your profile credentials.
use Aws\S3\S3Client;
$client = S3Client::factory(array(
'credentials' => array(
'key' => 'YOUR_AWS_ACCESS_KEY_ID',
'secret' => 'YOUR_AWS_SECRET_ACCESS_KEY',
)
));
And, if the bucket already exists, you can upload your file from the file system like this:
$result = $client->putObject(array(
'Bucket' => $bucket,
'Key' => $file_name,
'SourceFile' => $pathToFile
));

How to use AWS sdk in PHP for file operations for s3 and ec2?

I stuck up in a situation where I need to write files to S3 and EC2 as well.
The below code is perfectly working to write files to S3, but dont know how to write to EC2.
<?php
if(file_exists('aws-autoloader.php')){
require 'aws-autoloader.php';
}else{
die( 'File does not exist');
}
define('AWS_KEY','*****');
define('AWS_SECRET','********');
use Aws\S3\S3Client;
use Aws\Credentials\Credentials;
$credentials = new Credentials(AWS_KEY, AWS_SECRET);
$client = new S3Client([
'version' => 'latest',
'region' => 'ap-southeast-1',
'credentials' => $credentials
]);
$client->registerStreamWrapper();
file_put_contents('s3://mybucket/abc/a.txt', 'test');
#chmod('/var/app/current', 0755);
//Not able to write the content to EC2 instance
#file_put_contents('/var/app/current/b.txt', 'test');
#file_put_contents('file://var/app/current/b.txt', 'test');
?>
It works without any problem with below code, if the application is having write permission.
file_put_contents('/var/app/current/b.txt', 'test');
or
file_put_contents('file:///var/app/current/b.txt', 'test');

Response logging in AWS PHP SDK v3

In v2 of the AWS PHP SDK, I was able to setup logging of request and response information by simply doing this:
<?php
use Monolog\Logger;
use Guzzle\Log\MonologLogAdapter;
use Guzzle\Plugin\Log\LogPlugin;
use Aws\S3\S3Client;
$monolog = new Logger('main');
$monolog_adapter = new MonologLogAdapter($monolog);
$log_plugin = new LogPlugin($monolog_adapter);
$s3_client = S3Client::factory(['region' => 'us-east-1']);
$s3_client->addSubscriber($log_plugin);
var_dump($s3_client->doesObjectExist('my-bucket', 'object-that-doesnt-exist'));
# This is the log entry I want in the v3 version:
# [2015-10-30 14:47:20] main.ERROR: myhostname aws-sdk-php2/2.8.20 Guzzle/3.9.3 curl/7.43.0 PHP/5.5.23 - [2015-10-30T14:47:20+00:00] "HEAD /my-bucket/object-that-doesnt-exist HTTP/1.1" 404 ...
# bool(false)
In v3, I cannot seem to find the solution. Middlewares do not seem helpful as they only fire before the request is sent, and thus I cannot access the response HTTP code.
Guzzle v6 has this feature built into its Middlewares, but I do not know how to get it to work with the aws-php-sdk. https://github.com/guzzle/guzzle/blob/master/src/Middleware.php#L180
The closest I got was this:
<?php
use Monolog\Logger;
use GuzzleHttp\MessageFormatter;
use GuzzleHttp\Middleware;
use GuzzleHttp\HandlerStack;
use Aws\S3\S3Client;
$monolog = new Logger('main');
$guzzle_formatter = new MessageFormatter(MessageFormatter::CLF);
$guzzle_log_middleware = Middleware::log($monolog, $guzzle_formatter);
$guzzle_stack = HandlerStack::create();
$guzzle_stack->push($guzzle_log_middleware);
$s3_client = new S3Client([
'region' => 'us-east-1',
'version' => '2006-03-01',
'http_handler' => $guzzle_stack,
]);
var_dump($s3_client->doesObjectExist('my-bucket', 'object-that-doesnt-exist'));
# [2015-10-30 15:10:12] main.INFO: myhostname aws-sdk-php/3.9.2 - [30/Oct/2015:15:10:12 +0000] "HEAD /my-bucket/object-that-doesnt-exist HTTP/1.1" 404 [] []
# bool(true)
However, while the logging works, doesObjectExist() now returns the incorrect value because this handler does not throw an exception for 404, which the aws-php-sdk expects to happen. Some other simple requests like uploading to S3 seemed to work at first glance. Not sure where else there could be issues with this method.
The handler used in the SDK is a bit different from the one used in Guzzle. You're creating a Guzzle handler correctly, and to pass that into the SDK, you would need to create an adapter like so:
<?php
use Aws\Handler\GuzzleV6\GuzzleHandler;
use Aws\S3\S3Client;
use Monolog\Logger;
use GuzzleHttp\Client;
use GuzzleHttp\MessageFormatter;
use GuzzleHttp\Middleware;
use GuzzleHttp\HandlerStack;
$guzzle_stack = HandlerStack::create();
$guzzle_stack->push(Middleware::log(
new Logger('main'),
new MessageFormatter(MessageFormatter::CLF)
));
$handler = new GuzzleHandler(new Client(['handler' => $guzzle_stack]));
$s3_client = new S3Client([
'region' => 'us-east-1',
'version' => '2006-03-01',
'http_handler' => $handler,
]);
var_dump($s3_client->doesObjectExist('my-bucket', 'object-that-doesnt-exist'));
The GuzzleHandler object converts HTTP errors to exceptions.
With aws/aws-sdk-php 3.212.7, registering a custom logger as shown by #giaour did not work for me.
The configuration supports a debug key now:
$s3_client = new S3Client([
'region' => 'us-east-1',
'version' => '2006-03-01',
'debug' => true,
]);
This shows the data transferred, but not the URLs used.

Categories