transfer file from AWS s3 budget to ec2 instance using php - php

I have been working on a project where we will have a website process on EC2 server. In my project, I was able to write a php code that allow users to upload file from web server to AWS S3 budget. However, in order to access that file from EC2, i think we need to transfer file from S3 budget to EC2 instance. I saw that there is a unix command line way to do that, but the project i'm working on is based on PHP/HTML/JSON. I wonder is there a way or tutorial to access or transfer file from S3 to EC2 instance using PHP?
Thanks

You do not need to transfer the file from S3 to EC2, in fact, this would be a waste of resources. Instead, you can generate a signed url pointing to the file directly on S3 (even if the bucket/file is private). This link can also be set to expire after a certain period. Here's an example using the AWS PHP SDK:
<?php
require 'aws-autoloader.php'; //SDK autoloader file
//*** Initiate an S3 client
$client = S3Client::factory(array(
'key' => "public_key",
'secret' => "private_key",
'region' => "your s3 region"
));
$url = $client->getObjectUrl("bucket_name", "full_object_name", "+1 minutes"[optional]);
echo $url; //Print the direct S3 link to the file, which will expire in 1 minute.
//This will work even if the bucket is private.
[update]
If you still need to download the file from S3 to EC2, do this:
<?php
require 'aws-autoloader.php'; //SDK autoloader file
//*** Initiate an S3 client
$client = S3Client::factory(array(
'key' => "public_key",
'secret' => "private_key",
'region' => "your s3 region"
));
$result = $client->getObject(array(
'Bucket' => "bucket_name",
'Key' => "name of file",
'SaveAs' => "ec2 path to save the file at"
));
echo $result; //make sure download worked.
Further reading:
http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.S3.S3Client.html

Related

Error when calling AWS Lambda from PHP script hosted on Apache but can from same script run directly

I have a PHP (8.1.8) page hosted on Apache (2.4) on a Windows Server 2019 EC2 instance in AWS. It attempts to send an event to a Lambda Function. The page is called with HTTP, not HTTPS (don't ask - required for external calling system).
If I run the script in VSCode (for example) it works fine and I get a response from the Lambda Function (so I believe the EC2 instance has no problem talking to the Lambda Function). However if I request the page through a browser I get an error (XXXXX represents my Lambda Function name, obfuscated):
Fatal error: Uncaught exception 'Aws\Lambda\Exception\LambdaException' with message 'Error executing "Invoke" on "https://lambda.eu-west-1.amazonaws.com/2015-03-31/functions/XXXXX/invocations"; AWS HTTP error: Connection refused for URI https://lambda.eu-west-1.amazonaws.com/2015-03-31/functions/XXXXX/invocations' GuzzleHttp\Exception\ConnectException: Connection refused for URI https://lambda.eu-west-1.amazonaws.com/2015-03-31/functions/XXXXX/invocations in C:\Apache24\htdocs\vendor\guzzlehttp\guzzle\src\Handler\StreamHandler.php:328
The script is:
<?php
require 'vendor/autoload.php';
use Aws\Credentials\Credentials;
use Aws\Lambda\LambdaClient;
$data = 'TEST PAYLOAD';
$array_obj = array("xml" => $data);
$json_obj = json_encode($array_obj);
$credentials = new Aws\Credentials\Credentials('<<KEY>>', '<<SECRET>>');
$client = new Aws\Lambda\LambdaClient([
'version' => 'latest',
'region' => 'eu-west-1',
'credentials' => $credentials,
'debug' => false,
]);
$lambda_result = $client->invoke([
'FunctionName' => 'XXXXX',
'InvocationType' => 'RequestResponse',
'LogType' => 'None',
'Payload' => $json_obj,
]);
print_r(json_decode($lambda_result->get('Payload')->getContents(), true))
?>
I'm pretty sure I'm just missing some config that will allow the web page script to call the Lambda, but I'm drawing a blank searching around for an answer.
EDIT:
Edited to clarify that this is running on a Windows Server 2019 EC2 instance, and the page is called with HTTP, not HTTPS.
EDIT 2:
I get the same issue with SQS, so its not a Lambda thing specifically. Seems to be generally about accessing AWS resources through the SDK APIs? (Tags adjusted accordingly)

AWS dynamodb query from php

I have a react application and i'm trying to use aws dynamodb, i installed the php sdk but i don't know how to query my db.
I copied the tutorial here and i changed the endpoint to: "https://dynamodb.us-west-2.amazonaws.com".
I get this error: {"__type":"com.amazon.coral.service#UnrecognizedClientException","message":"The security token included in the request is invalid."}. I guess i have to add a security token somewhere, i don't know where and neither where to find it.
Any suggestion?
Based on your error, i think you need to check your aws secret key and access key. You can try to install aws cli then create user access programmatically from aws console from this link
Then you can try your source code after that.
The following code example shows how to get an item from a DynamoDB table.
// '/path/to/aws-autoloader.php' to import AWS SDKs.
require 'vendor/autoload.php';
use Aws\DynamoDb\DynamoDbClient;
use Aws\Exception\AwsException;
use Aws\DynamoDb\Exception\DynamoDbException;
// Create an SDK class used to share configuration across clients.
$sdk = new Aws\Sdk([
'region' => 'us-west-2',
'version' => 'latest'
]);
// Use an Aws\Sdk class to create the dynamoDbClient object.
$dynamoDbClient = $sdk->createDynamoDb();
try {
$dynamoDbClient->getItem([
'Key' => [
'id' => [
'N' => 1,
],
],
'TableName' => 'products',
]);
} catch (DynamoDbException $e) {
// Catch a DynamoDb-specific exception.
echo $e->getMessage();
} catch (AwsException $e) {
// This catches the more generic AwsException. You can grab information
// from the exception using methods of the exception object.
echo $e->getAwsRequestId() . "\n";
echo $e->getAwsErrorType() . "\n";
echo $e->getAwsErrorCode() . "\n";
// This dumps any modeled response data, if supported by the service
// Specific members can be accessed directly (e.g. $e['MemberName'])
var_dump($e->toArray());
}
Notice that we did not explicitly provide credentials to the client. That’s because the SDK should detect the credentials from environment variables (via AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY), an AWS credentials INI file in your HOME directory, AWS Identity and Access Management (IAM) instance profile credentials, or credential providers.
If we don’t provide a credentials option, the SDK attempts to load credentials from your environment in the following order:
Load credentials from environment variables.
Load credentials from a credentials .ini file.
Load credentials from IAM role.
We can also directly create the service-specific client object like below:
$dynamoDbClient = new DynamoDbClient(
[
'region' => 'us-west-2',
'version' => 'latest',
]
But AWS highly recommended that you use the Sdk class to create clients if you’re using multiple client instances in your application. As per AWS docs:-
The Sdk class automatically uses the same HTTP client for each SDK
client, allowing SDK clients for different services to perform
nonblocking HTTP requests. If the SDK clients don’t use the same
HTTP client, then HTTP requests sent by the SDK client might block
promise orchestration between services.
You can refer to the AWS document pages:-
AWS SDK PHP - BASIC USAGE
AWS SDK PHP - DynamoDB Examples
AWS SDK PHP - Configuration guide
AWS SDK PHP - APIs
I hope this helps.

unable to upload image file to S3 bucket via PHP

I am trying to upload an image to my S3 Bucket via AWS PHP SDK. For my EC2 instance, I have attached a role that allows PutObject and GetObject for my S3 Bucket. Therefore, I do not need to attach credentials when creating the S3Client, supposedly. I'm still learning.
Here is my PHP script:
<?php
require './aws/aws-autoloader.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
use Aws\Credentials\Credentials;
$s3 = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-east-1'
]);
$filename = $_FILES['file']['name'];
try {
$result = $s3->putObject([
'Bucket' => 'bucket name',
'Key' => 'testimage1',
'Body' => $filename
]);
echo 'DONE';
} catch (Exception $e) {
echo $e;
}
I keep getting a 500 internal error in this form. Apparently the error occurs at S3Client creation, I'm not sure why.
Further probing confirms, that when I try to instantiate the S3Client class, the 500 internal error is thrown. I am able to access the S3 bucket from the CLI but unable to do so using the AWS PHP SDK.
Here is the image of the error:
Can anyone advice in this? Thank you for reading.
According to the docs, the use of the S3Client Class is like this: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_configuration.html
use Aws\S3\S3Client;
$options = [
'region' => 'us-east-1',
'version' => '2006-03-01',
'signature_version' => 'v4'
];
$s3Client = new S3Client($options);
It also says, "We do not recommend Using latest in a production application because pulling in a new minor version of the SDK that includes an API update could break your production application."
I solved it but I used composer. So here's a step by step guide.
This is under the assumption that you have created an IAM role with full S3 access or at least with the PutObject policy attached, and the IAM role is attached to the EC2 instance. Also that your EC2 instance has installed a web server.
In the EC2 instance /var/www/html (folder where your web server hosts your webpage), install composer as guided through here in your project folder. I chose to install composer globally for convenience sake.
Install AWS PHP SDK as seen in this guide.
If you an encounter an error asking for simplexml extension, just yum install php-xml and rerun the installation of AWS PHP SDK.
Now that you have the SDK installed, you can now upload the file you want to the S3 bucket.
Here is my code for uploading, my vendor folder is root level with the php file used for uploading files to the S3 bucket.
require 'vendor/autoload.php';
use Aws\S3\S3Client;
try{
$sharedConfig = [
'region' => 'us-east-1',
'version' => 'latest'
];
$sdk = new Aws\Sdk($sharedConfig); /*Instantiate SDK class with configs for API use*/
$s3Client = $sdk->createS3(); /*creates the S3 Client for API use*/
$file_name = $_FILES['file']['name']; /*file name e.g. name.jpg */
$file_tmp_name = $_FILES['file']['tmp_name']; /*!!! IMPORTANT - this is what you need to supply the SourceFile to properly upload the file*/
$file_type = $_FILES['file']['type']; /*file type*/
/*print_r($_FILES['file']);*/
$result = $s3Client->putObject([
'Bucket' => 'bucket-name',
'Key' => 'testimage.jpg',
'SourceFile' => $file_tmp_name,
'ContentType'=>$file_type,
'ContentDisposition'=>'attachment'
]);
echo "FILE SENT";
}catch(Exception $e){
echo $e;
}

AWS s3 functions work on local but not on AWS server

I am working on a project where users can upload objects in their own directory in server and this is my approach that works on localhost to create user directories:
$s3Client = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'ca-central-1'
]);
$s3Client->registerStreamWrapper();
$s3Dir = 's3://' . $bucketName . '/' . $folderName;
file_put_contents($s3Dir, '');
Since the code is working on local, I think it's not the problem of s3 permissions or bucket policies. My guess is php setting on AWS server is causing the issue.
Any help would be great!

Amazon S3 basic action doesn't work

I'm trying to use Amazon S3 to store my images.
What I've done so far is installing the AWS SDK via PEAR (link: http://docs.aws.amazon.com/aws-sdk-php-2/guide/latest/installation.html)
Then I've gone to the second step, creating a client:
<?php
// Include the SDK using the Composer autoloader
require 'vendor/autoload.php';
use Aws\S3\S3Client;
// Instantiate the S3 client with your AWS credentials and desired AWS region
$client = S3Client::factory(array(
'key' => 'your-aws-access-key-id',
'secret' => 'your-aws-secret-access-key',
));
My keys are set correctly ... .
Then I want to test all this by creating a bucket like this:
$bucket = 'my-bucket';
try{
$result = $client->createBucket(array(
'Bucket' => $bucket
));
// Wait until the bucket is created
$client->waitUntil('BucketExists', array('Bucket' => $bucket));
}
catch(Exception $e){
var_dump($e->getMessage());
}
But I always get this error:
The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.
I think my SDK isn't properly installed ... Can anyone help me with this? I'm using vagrant so I installed the AWS SDK in my root folder with this command:
sudo pear -D auto_discover=1 install pear.amazonwebservices.com/sdk
I got the message that is was installed ok.
I've also did a var_dump of my $client. The link to my response: http://pastebin.com/KqkEiKGs
Don't now if you're something with it ... (My keys are hidden)
Your error message says it - you are trying to use the name that is not unique for your bucket, you should use some more unique names. And, yes, bucket names must be unique across all of Amazon S3 (not only your account).
You can read more about it here.

Categories