How to Use Amazon S3 & PHP to Dynamically Store and Manage Files with Ease


A couple of weeks ago, Nettuts+ posted an introductory tutorial to using Amazon's Simple Storage System (S3). Being able to upload an unlimited number of files for hardly any money is great, but it would be even better if your users could upload files from your website. That way you wouldn't have to worry about the size of your web server for a second. Let's try!

Basically what we're going to do is use a standard HTML file element and an easy to use S3 PHP class to make a page where people can upload a file to your S3 account and get information about the files that have already been uploaded. For this you'll need an Amazon S3 account and a PHP enabled webserver. If you haven't heard about Amazon S3, or you don't have an account yet, read Collis' Introductory S3 Tutorial first.

Step 1

Now, the first thing we'll need is a way for PHP to communicate with the S3 server. Donovan Schonknecht has written a PHP class for this, so rather than trying to reinvent the wheel, we'll use that!

  1. Download the 'latest beta version (0.2.3)'
  2. Extract the .rar file and copy the S3.php file to a new folder. The file comes with a readme and a few examples, too, but we won't be using those.
  3. Open the S3.php file and take a look around just to see all the work you will not be doing yourself thanks to this class! :-)

Step 2

Next, make a new file called page.php in the same folder. First thing we'll need to do is include the S3.php file. We'll use the require_once() function in php. This function will include the file only if it wasn't included before on the same page. This is to make sure that we won't run into any problems with function redefinitions when accidentally the script tries to include the file a second time.

Next, we'll have to enter the Amazon Web Services (AWS) access information the script needs to access our S3 server. These are the Acces Key and the Secret Key provided by Amazon (again, if you don't know what I'm talking about see the introductory NETTUTS tutorial). Now we have all the information needed to initiate the class. This code was put in the very top of the body tags.

//include the S3 class				
if (!class_exists('S3'))require_once('S3.php');

//AWS access info
if (!defined('awsAccessKey')) define('awsAccessKey', 'CHANGETHIS');
if (!defined('awsSecretKey')) define('awsSecretKey', 'CHANGETHISTOO');

//instantiate the class
$s3 = new S3(awsAccessKey, awsSecretKey);

//we'll continue our script from here in step 4!


Step 3

Now let's make a simple html form with a file element in it. This element allows users to browse their local drive for a file. When the user presses the submit button the file will automatically be uploaded as a temporary file to the server and information about the file will be sent in the POST variable.

Here's the code snippet. Be sure not to forget enctype="multipart/form-data" which is necessary for the file element to work. This code should be placed outside the <?php ?> tags, since it is HTML.

<form action="" method="post" enctype="multipart/form-data">
  <input name="theFile" type="file" />
  <input name="Submit" type="submit" value="Upload">

Step 4

Now, for those unfamilliar with forms, action="" tells the script which page to go to after submitting. Since we specified an empty string there, the form will post the variables and then refresh the current page. So when the page gets loaded, we'll want to check whether or not a form was submitted.When a form was submitted the page should execute the script that retreives the post variables and takes care of moving the files to the S3 server.

The post variable sent by the file element is an array, containing information about the file. For example: filename, size, type and temporary name. All we'll need is the filename and the temporary name. Note that, unlike other form elements, the file element will send the variables to $_FILES and not to $_POST.

The PHP code below checks whether a form was submitted and retreives the post variables. We'll deal with the S3 server later. This code should be placed right after where we initiated the s3 class.

//check whether a form was submitted

    //retreive post variables
    $fileName = $_FILES['theFile']['name'];
    $fileTempName = $_FILES['theFile']['tmp_name'];
    //we'll continue our script from here in the next step!

Step 5

Ok, so now we have a form that sends a temporary file to the server and leaves you with some information. If you like, you can upload the file to a server and test it. You'll notice that it indeed takes some time to process the form, since it is in fact uploading a file. Anyway, you won't see the file appear anywhere on your server because it was only stored as a temporary file. All that's left to do is to move our uploaded file to a bucket. First we'll create a new bucket and then we'll move the file to that bucket.

To create a bucket we'll use the function putBucket(bucket, acl) in which 'bucket' is the name of the bucket (Amazon's word for your main folder or directory of files). The second argument is the Access Control List (ACL) in which you can define who can and who cannot read from or write to this bucket. We want anybody to be able to read our files, so we'll use S3::ACL_PUBLIC_READ. Note that a bucket only needs to be created once, so every next time this script is executed this function won't do anything, since the bucket already exists.

To move the file we'll use the function putObjectFile(sourcefile, bucket, newfilename, acl).The sourcefile is the path to the file we want to move, so in our case it is the temporary file that was uploaded through our form. Bucket is the bucket to move the file to, which will be the bucket we just created. Newfilename is the filename the file will get in the bucket. In this tutorial we'll use the same filename as on the local drive, but in some cases you might want to change filenames. Acl again is the Access Control List, which we'll again set to S3::ACL_PUBLIC_READ.

//create a new bucket
$s3->putBucket("jurgens-nettuts-tutorial", S3::ACL_PUBLIC_READ);

//move the file if ($s3->putObjectFile($fileTempName, "jurgens-nettuts-tutorial", $fileName, S3::ACL_PUBLIC_READ)) { echo "We successfully uploaded your file."; }else{ echo "Something went wrong while uploading your file... sorry."; }

Step 6

Now when you select a file and hit 'Upload' the file will be stored on the amazon server. You can already view it just by entering a URL that looks like this:

For the finishing touch we'll want the script to output a list of files in the bucket. For this we'll use the function getBucket(bucket), in which bucket is the bucket we want to output. This function returns an array with information about the files. Each returned as an array, too. To visualize:

We want to output every file in the $bucket_contents array. For this we'll use a foreach() loop which will loop through the array until all elements have been processed. It will store the current element in the $file variable and execute the code in between the brackets. All we need to do now is echo a link to the file.

Place this code under the form to show the list there.

// Get the contents of our bucket
$bucket_contents = $s3->getBucket("jurgens-nettuts-tutorial");

foreach ($bucket_contents as $file){

    $fname = $file['name'];
    $furl = "".$fname;
    //output a link to the file
    echo "<a href=\"$furl\">$fname</a><br />";

With a little css styling, your final result might look like this:


So there you have it, your own unlimited file upload script. Of course there's a lot more you can do with the S3 PHP class. Just take a quick glance at its readme file and you'll be good to go. It's really easy to use!

Download the source files

View a demo

Related Posts
  • Computer Skills
    App Training
    Writing Destinations for DropzoneDropzone400
    Dropzone is not just another FTP upload client, but a great utilities platform for processing files and text. Dropzone is a collection of destinations that can have two types of actions: drag and drop action and/or a click action. There are a lot of pre-programmed destinations to use, but you can also write your own destinations in Ruby!Read More…
  • Code
    Theme Development
    Custom Controls in the Theme CustomizerTheme customizer custom control 400
    In the last article, we explored the advanced controls available in the Theme Customizer, and how to implement them. We’re going to look at how to create our own custom control, allowing you to choose which Category of Posts are displayed on the home page. To get started, download version 0.6.0 of our Theme Customizer Example.Read More…
  • Code
    Setting Up a Local Mirror for Composer Packages With SatisComposer retina preview
    Installing all your PHP libraries with Composer is a great way to save time. But larger projects automatically tested and run at each commit to your software version control (SVC) system will take a long time to install all the required packages from the Internet. You want to run your tests as soon as possible through your continuous integration (CI) system so that you have fast feedback and quick reactions on failure. In this tutorial we will set up a local mirror to proxy all your packages required in your project's composer.json file. This will make our CI work much faster, install the packages over the local network or even hosted on the same machine, and make sure we have the specific versions of the packages always available.Read More…
  • Code
    Creating a Photo Tag Wall With Twilio Picture Messaging & PHPProcedural to oop php retina preview
    Twilio's recently announced Picture Messaging has vastly opened up what we can do with text messaging, now we can attach photos to our text messages and have them get used in different ways. In our case, we are going to build a Photo Tag Wall, which will contain photos linked to tags that will be displayed on a website.Read More…
  • Code
    Acceptance Testing With CodeceptionIntro to codeception retina preview
    Typically new features for web applications are tested by visiting the appropriate page in a browser, maybe filling out some form data, submitting the form, and then developers or testers hope to see their desired result. This is the natural way most web developers test their apps. We can continue with this natural testing process and improve upon it to ensure our apps are as stable as possible by using Codeception. Read More…
  • Code
    Using HighCharts in WP-AdminHighcharts 400
    Charts are a great way to present data. They make data more digestible by making it visually appealing. In WordPress, there is no built-in method for getting posts and pages data in a graphical form. Although, there are certain plugins available which integrate Google Analytics with WordPress, but they are overkill if you want to get only a portion of that data. Also, nothing should keep you from learning new techniques and to dive straight into the subject is the best way to learn.Read More…