11

I have my pictures on Amazon S3. The pictures are private and not public so I can not show them with a direct link s3.amazonaws/bucket_name/key_name/image_name.jpg

I know the image names on Amazon S3. How do I show for example the Amazon S3 images flower.png and house.png on my website with PHP?

Xtreme
  • 1,601
  • 7
  • 27
  • 59

4 Answers4

11

For those who needs this behavior with AWS SDK v3, if you directly call getObjectUrl with '+10 minutes' as third parameter, it will always return the plain URL. That's because the method changed. To get the pre-signed link, do the following:

//Get an instance of S3 Client. This is one one to do it:
$s3Client = new S3Client([
    'version'     => 'latest',
    'region'      => 'us-west-2', //Region of the bucket
    'credentials' => array(
        'key' => 'YOUR-ACCOUNT-KEY',
        'secret'  => 'YOUR-ACCOUNT-SECRET',
    )
]);

//Get a command to GetObject
$cmd = $s3Client->getCommand('GetObject', [
    'Bucket' => 'YOUR-BUCKET-NAME',
    'Key'    => 'YOUR-FILE-KEY'
]);

//The period of availability
$request = $s3Client->createPresignedRequest($cmd, '+10 minutes');

//Get the pre-signed URL
$signedUrl = (string) $request->getUri();

Ref: https://docs.aws.amazon.com/aws-sdk-php/v3/guide/service/s3-presigned-url.html

Laerte
  • 7,013
  • 3
  • 32
  • 50
9

If you don't want to make your file public, here is the procedure.

  1. ensure your S3 bucket is private. Only authenticated and authorised calls are allowed to get your objects

  2. on the server side, when rendering the page, generate links to S3 object that include a signature. The signature will be computed from your access and secret key and will tell S3 that the call must be authorised

S3 Signed URL are easy to generate from our SDK. For PHP, just check the doc at http://docs.aws.amazon.com/aws-sdk-php/guide/latest/service-s3.html#creating-a-pre-signed-url

  1. in the web page, when the user will click a signed URL, the browser will be directed to S3. S3 will verify the signature and - when correct - will get the object
Sébastien Stormacq
  • 14,301
  • 5
  • 41
  • 64
  • To access a Google Cloud Storage file using PHP in Google App Engine I use the following, gs://bucket_name/desired_object_name. That is easy, what you linked to is not easy. Do you have any links to easier ways to access a private file in Amazon S3 using PHP? Something like $s3->getPrivateLink( 'myfile.jpg', +10 ); which returns the temporary link? – Mike Jul 27 '16 at 23:35
  • Sure, have a look at http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html#creating-a-pre-signed-url one line of code is enough $signedUrl = $client->getObjectUrl($bucket, 'data.txt', '+10 minutes'); – Sébastien Stormacq Aug 03 '16 at 22:31
  • Thank you! If anyone is looking for the python code for this - https://stackoverflow.com/a/33698531/326835 – Harshad Vyawahare Mar 24 '21 at 12:07
2

Easiest thing to do is make them public in s3, at least read-only.

If you don't want them to be public on s3, for whatever reason, you could add a cloudfront distribution that will serve the images from your s3 bucket, and you can give cloudfront access to the files, without making the images public in s3.

This link shows you how to do that:

http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html

E.J. Brennan
  • 45,870
  • 7
  • 88
  • 116
  • 7
    The reason I do not want to make them public on S3. The pictures are uploaded by users on my website. Images should not be found via search engines or in any other way. Only authorized users should be able to see selected images through my website. – Xtreme Jan 05 '15 at 00:03
0

Create a REST API with Amazon API Gateway and invoke a lambda function with necessary user permissions to access data from a private s3 bucket.
Use the following code to send a base64 response back.
This can directly be used as source of the image tag in HTML.

const AWS = require('aws-sdk');
//*/ get reference to S3 client 
var s3 = new AWS.S3();
exports.handler = (event, context, callback) => {
    var params = {
  "Bucket": "bucket-name",
  "Key": "object-name"  
    };
    s3.getObject(params, function(err, data){
       if(err) {
           callback(err, null);
       } else {
           let image = new Buffer(data.Body).toString('base64');
           image = "data:"+data.ContentType+";base64,"+image;
           let response = {
        "statusCode": 200,
        "headers": {
            "Access-Control-Allow-Origin": "*",
            'Content-Type': data.ContentType
        },
        "body":image,
        "isBase64Encoded": true
    };
           callback(null, response);
    }
    });
    
};