How to put objects on AWS S3 bucket using PHP 7

How to put objects on AWS S3 bucket using PHP 7

  • 10
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
    10
    Shares

Amazon Web Services are one of the most used web services that are used for various services. From hosting a website on their servers to server-less architecture they provide huge number of services to their users.

According to Wiki, AWS operates from many global geographical regions including 6 in North America. In 2017, AWS comprised more than 90 services spanning a wide range including computing, storage, networking, database, analytics, application services, deployment, management, mobile, developer tools, and tools for the Internet of Things.

While creating or connecting with these services it is important to provide the correct region. AWS doesn’t allow to access the services with incorrect region details.

What I used here:

  • PHP 7.1
  • Laravel 5.6

Install AWS SDK

In order to work on AWS services with PHP, you can choose to use PHP dependency manager i.e., composer to install AWS SDK with your application.

You can use below command to install AWS  SDK with your Laravel Application

composer require aws/aws-sdk-php

Create a Separate class for AWS interaction

In order to maintain, the maintainability of the application, I would recommend creating a separate class that will contain the interaction with AWS services. This call will handle the connection with S3 Bucket, uploading the object in the bucket, etc.

<?php
namespace App\Http\Controllers;
 
use Aws\S3;
use Aws\S3\S3Client;
 
/**
 * Description of AWSS3BucketInteraction
 *
 * @author <Author name>
 */
class AWSS3BucketInteractionController extends Controller
{
 public function __construct()
    {
     // Construct code here        
    }
}

Create a method to Connect with S3 bucket

I created a  separate function to connect the S3 bucket and used this connection in the constructor, so that whenever, I try to initialize this class, the connection will already be ready to use.

public function connectWithS3Bucket($key, $secret)
    {
        $credentials = new \Aws\Credentials\Credentials($key, $secret);
        
        $s3Client = new S3Client([
            'region' => <region>,
            'version' => <api version>,
            'credentials' => $credentials
        ]);
 
        return $s3Client;
    }

I have tried two ways to connect with the S3 bucket.

Put the credentials on server root

With this way, we can create a credential file on server (Linux) root. You need to go to the root and create a hidden folder named as “.aws”, then create a file named as “credentials”.

[default]

aws_access_key_id = <access key>

aws_secret_access_key = <Secret>

 

This is the default setting AWS use and pick the credentials from there.

public function connectWithS3Bucket()
    {
        $s3Client = S3Client::factory([
            'profile' => 'default',
            'region' => 'us-west-1',
            'version' => self::AWS_API_VERSION,
        ]);
 
        return $s3Client;
    }

In the above function, we have used default profile and this tells SDK to pick the credentials from “/.aws/credentials” file. If you have any issue connecting with this, you can simply give the path of the credential file as below

public function connectWithS3Bucket()
    {
        //pick credentials manually
        $credentialsFile = public_path('../.aws/credentials');
        $credentials = \Aws\Credentials\CredentialProvider::ini('default', $credentialsFile);
        $s3Client = S3Client::factory([
            'profile' => 'default',
            'region' => 'us-west-1',
            'version' => self::AWS_API_VERSION,
            'credentials' => $credentials
        ]);
 
        return $s3Client;
    }

Access credentials from settings or .env file

This is another way by which you can connect to the S3 Bucket. So using this my class will look like

<?php
 
namespace App\Http\Controllers;
 
use Aws\S3;
use Aws\S3\S3Client;
 
/**
 * Description of AWSS3BucketInteraction
 *
 * @author <author name>
 */
class AWSS3BucketInteractionController extends Controller
{
    private $awsSecretKey;
    private $awsAccessSecretKey;
    protected $s3Connection;
    protected $bucketName;
 
    const AWS_API_VERSION = '2006-03-01';
    
    public function __construct()
    {
        $this->awsSecretKey = env('AWS_ACCESS_KEY_ID');
        $this->awsAccessSecretKey = env('AWS_SECRET_ACCESS_KEY');
 
        $this->s3Connection = $this->connectWithS3Bucket($this->awsSecretKey, $this->awsAccessSecretKey);
    }
 
    public function connectWithS3Bucket($key, $secret)
    {
        $credentials = new \Aws\Credentials\Credentials($key, $secret);
        
        $s3Client = new S3Client([
            'region' => <region>,
            'version' => self::AWS_API_VERSION,
            'credentials' => $credentials
        ]);
 
        return $s3Client;
    }
}

Create a method to upload the image/PDF to the Bucket

This method contains the folder structure which needs to be created on the bucket. Now suppose, you want to put your object inside a proper folder structure as <bucket name>/Digvijay/PDF/<pdf-name>.pdf. Then this should be defined in putObject() function provided by SDK for S3. If the folder inside the complete structure found at its place then putObject will just place the object at a defined place else it will create the folder and place the object.

 

putObject takes four parameters to process the file.

  1. Bucket: Name of S3 Bucket that needs to be used
  2. Key: The complete structure of the file system where the object needs to be placed including the object name and extension.
  3. Body: Content of the file
  4. ACL: Full form of ACL is  Access Control List, You will just need to pick a access key for this file.  
public function uploadPdfToS3($userName, $fileName, $pdfOutput)
    {
        try {
            // Upload data.
            $result = $this->s3Connection->putObject([
                'Bucket' => env('AWS_BUCKET'),
                'Key' => $userName . '/DF/' .$fullName . '-' . time() . '.pdf',
                'Body' => $pdfOutput,
                'ACL' => 'public-read'
            ]);
 
            // Print the URL to the object.
            return $result['ObjectURL'];
        } catch (S3Exception $e) {
            return false;
        }
    }

So here is the complete class that is responsible to upload the PDF on S3 Bucket.

<?php
 
namespace App\Http\Controllers;
 
use Aws\S3;
use Aws\S3\S3Client;
 
/**
 * Description of AWSS3BucketInteraction
 *
 * @author <author name>
 */
class AWSS3BucketInteractionController extends Controller
{
    private $awsSecretKey;
    private $awsAccessSecretKey;
    protected $s3Connection;
    protected $bucketName;
 
    const AWS_API_VERSION = '2006-03-01';
    
    public function __construct()
    {
        $this->awsSecretKey = env('AWS_ACCESS_KEY_ID');
        $this->awsAccessSecretKey = env('AWS_SECRET_ACCESS_KEY');
 
        $this->s3Connection = $this->connectWithS3Bucket($this->awsSecretKey, $this->awsAccessSecretKey);
    }
 
    public function connectWithS3Bucket($key, $secret)
    {
        $credentials = new \Aws\Credentials\Credentials($key, $secret);
        
        $s3Client = new S3Client([
            'region' => <region>,
            'version' => self::AWS_API_VERSION,
            'credentials' => $credentials
        ]);
 
        return $s3Client;
    }
 
public function uploadPdfToS3($userName, $fileName, $pdfOutput)
    {
        try {
            // Upload data.
            $result = $this->s3Connection->putObject([
                'Bucket' => env('AWS_BUCKET'),
                'Key' => $userName . '/DF/' .$fullName . '-' . time() . '.pdf',
                'Body' => $pdfOutput,
                'ACL' => 'public-read'
            ]);
 
            // Print the URL to the object.
            return $result['ObjectURL'];
        } catch (S3Exception $e) {
            return false;
        }
    }
 
}

How to use this class

 

You just need to create a object of this class and use this as below

 Namespace

use App\Http\Controllers\AWSS3BucketInteractionController;

Creating Object  

$this->s3bucket = new AWSS3BucketInteractionController();

Call the upload function

$this->s3bucket->uploadPdfToS3($userName, $fileName, $pdfOutput);

The above call will return the URL of PDF inside the S3 bucket.

Please test this code and let me know if you get any issue with it. Any suggestion to make this code better is most welcome.