Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / PHP

PHP AWS SDK (S3)

4.33/5 (2 votes)
4 Feb 2011CPOL2 min read 41.7K   537  
Using the PHP AWS SDK (S3) to upload and show private files.

Introduction

This code allows you to upload files to Amazon S3, keep them private (in other words, not have them visible/downloadable simply from a S3 URL), but have them accessible from your own web pages.

Background

This project uses the ideas from Donovan Schönknecht and Nettuts+ as points of departure. Donovan has written a S3 PHP interface and Nettuts+ has used his code to implement uploading images and showing hyperlinks to the uploaded images.

This implementation uses the AWS SDK PHP code from Amazon instead of Donovan's code, and keeps the files private as opposed to Nettuts+'s implementation which uploads files to S3 with full public access.

Using the Code

The source code provided includes the AWS SDK PHP (version 2011.01.14), but you can't simply unzip it, throw it on a web server, and make it run. Assuming you have PHP enabled, you still need to do the following things:

  1. Have an Amazon S3 account.
  2. Have a bucket called "bucket" (or change the code to look in a different bucket).
  3. Create a config.inc.php file with your own S3 credentials from the config-sample.inc.php that is included (keep your config.inc.php file in the same folder/directory).

At that point, you should be good to go!

The first part of the code in index.php simply uploads a file using a form:

PHP
$s3 = new AmazonS3();
$bucket = "bucket";

// check whether a form was submitted
if (isset($_POST['submit'])) {
    // retrieve post variables
    $file = $_FILES['file'];
    $filename = $file['name'];
    $tmpname = $file['tmp_name'];
    $contentType = $file['type'];

    // upload the file
    $fileResource = fopen($tmpname, 'r');
    try {
        $response = $s3->create_object($bucket, $filename, 
           array('fileUpload' => $fileResource, 'contentType' => $contentType));
        if ($response->isOK())
            echo "<strong>Upload of $filename succeeded.</strong>\n";
        else
            echo "<strong>Upload of $filename failed.</strong>\n";
    } catch (Exception $e) {
            echo 'Caught exception: ',  $e->getMessage(), "\n";
    }
}

Note that I've put it into a try/catch block because S3::create_object() can blow up (I've notice it do so when I've tried to upload files that are several megabytes).

The second part of index.php displays the files you have in the pre-designated bucket. It loops through the files in the bucket and checks if the file is an image file (a simplistic check of the file extension). If it is an image, it displays it, if not, it makes a hyperlink to it showing a document icon:

PHP
$response = $s3->list_objects($bucket);

$contents = $response->body->Contents;
foreach ($contents as $content) {
    $filename = $content->Key;
    echo "<p>$filename</p>\n";
    if (isImage($filename)) {
        echo "<img width='150' height='100' src='file." + 
             "php?bucket=$bucket&filename=$filename'/>\n";
    } else {
        echo "<a href='file.php?bucket=$bucket&filename=$filename'>" + 
             "<img width='50' height='50' src='document.png'/></a>\n";
    }
}

The hyperlink or the source of the image is gotten from the file.php file, which is very straightforward:

PHP
$bucket = $_GET['bucket'];
$filename = $_GET['filename'];

// Include the SDK
require_once 'sdk.class.php';

// Instantiate the class
$s3 = new AmazonS3();
$response = $s3->get_object($bucket, $filename);
$contentType = $response->header['_info']['content_type'];
header("Content-type: $contentType");
header("Content-Disposition: filename=$filename");
echo $response->body;

The only "magic" lies in the header directives which provide the content type and preserves the file name when downloading.

The only thing missing is more defensive code in both files that restricts its access. I'll leave that up to the reader as an exercise :-)

Points of Interest

At first, I was stupidly futzing around with PHP GD to make the images appear. However, there's no need for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)