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

Jun 5th in PHP by Jürgen Visser

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!

PG

Author: Jürgen Visser

I'm a freelance webdesigner based in The Netherlands. I mostly work in Flash but I also do a lot of HTML and PHP. Visit my website to learn more about me!

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.

<?php
//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">
</form>

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
if(isset($_POST['Submit'])){

    //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: http://yourbucketname.s3.amazoneaws.com/yourfile.ext

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.

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

foreach ($bucket_contents as $file){

    $fname = $file['name'];
    $furl = "http://jurgens-nettuts-tutorial.s3.amazonaws.com/".$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:

Finished!

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

Check out some more great tutorials and articles that you might like

Enjoy this Post?

Your vote will help us grow this site and provide even more awesomeness

Plus Members

Source Files, Bonus Tutorials and
More for $9 a month for all TUTS+
sites in one subscription.

Join Now

User Comments

( ADD YOURS )
  1. PG

    Mark Bowen June 5th

    Hi there,

    Nice tutorial. Would be nice if you could possibly add in some nice AJAX love to this to show feedback on how much of the file has been uploaded with a tutorial as to how to do that. Having unlimited space to upload files is great but even better if the end user gets feedback as to how long they may have to wait for their file to upload before they can upload another one or they may just think that the form has given in ;-)

    Just a thought though. Great tutorial.

    Best wishes,

    Mark

    ( Reply )
  2. Sweet one, I was looking for something like this. Amazon S3 really kicks arse. Thanks a bunch, will give it a try

    ( Reply )
  3. PG

    Ben Griffiths June 5th

    Nice little tut, thanks :)

    ( Reply )
  4. PG

    John Deszell June 5th

    Great Tut! I’ve been looking for something like this. I’ll have to start utilizing soon. Thanks again Netttus!

    ( Reply )
  5. PG

    James June 5th

    Nicely written tut! Amazon S3 is definitely something I’ll be using in future projects! :)

    ( Reply )
  6. PG

    Andrew Pryde June 5th

    Nice, looks like a very good idea. I will look into using amazon I think! I may release a slightly improved version of the script with some more functionality shortly as well so keep an eye out for it ;)

    Andrew

    ( Reply )
  7. PG

    Nate June 5th

    Very useful information, thanks.

    ( Reply )
  8. PG

    sir jorge June 5th

    Crazy stuff, i like it.

    ( Reply )
  9. PG

    Azeem June 5th

    Awesome tutorial. Quick question: In your example, if you click on one of the images, for example, it asks you to download the file instead of just displaying it on screen. Is there a way to fix that?

    ( Reply )
  10. PG

    Jurgenv June 5th

    Thanks guys.

    @Andrew: ofcourse there’s a lot more you can add to this script. I am using amazon S3 in several projects i’m working on, also making more use of the possibilities. When you get into using the s3 class you’ll notice there’s a lot more you can do with it :)

    ( Reply )
  11. PG

    crysfel June 5th

    Nice tut!! and it is very easy to do it, thx.

    ( Reply )
  12. PG

    Tor Løvskogen June 5th

    Nice tutorial, just wanted to chime in to say that the uploader doesn’t handle files with spaces in them very well.

    ( Reply )
  13. PG

    Noura Yehia June 5th

    I Still havent gotten around to try Amazon S3 yet, but each time I read something about it, it makes me more determined to try it.

    Thanks for the article, great as always :)

    ( Reply )
  14. PG

    Joefrey Mahusay June 5th

    Nice article! I will try this one.

    ( Reply )
  15. PG

    Danny June 5th

    Awesome, definitely useful

    ( Reply )
  16. PG

    Erik Reagan June 5th

    I will possibly be hosting podcast content on S3 soon and this will help a lot since I will have a few administrators. Thanks for the walk-through!

    ( Reply )
  17. PG

    Ian R-P June 5th

    I LOVE these tuts… but i’m running into errors now (both this downloadable version and the s3.php verion from the creators website).

    Parse error: syntax error, unexpected ‘)’, expecting ‘(’ in /homepages/31/d204952132/htdocs/iarp/scripts/s3/page.php on line 29

    Line 29 of page.php: $s3->putBucket(”iarp”, S3::ACL_PUBLIC_READ);

    It’s got me stumped. If anyones on msn and knows what my problem is iarp@cogeco.ca plz add me.

    ( Reply )
  18. PG

    PixlNinja June 5th

    A little stuff to limit the size of a file will be grate.. else you know what will happen on a public folder

    ( Reply )
  19. PG

    Shane June 6th

    A nice progression from the previous tutorial on Amazon S3.

    @Mark - there are a number of file progress upload scripts out there. This one uses PHP, but there are several others that use MooTools.

    You may find this jQuery multiple file upload plugin useful too.

    It would be nice if Line 2 in step 5 used instead of too, but hey - I’m not complaining.

    A great tutorial - thanks for posting. ;)

    ( Reply )
  20. PG

    Johny June 6th

    Well an interesting technique but in case of content control ?
    Why should i give Amazon the control about which pictures can be uploaded on my site ? Shouldn´t i decide it myself ? Who will be responsible for the stored files on the Amazon server ? Amazon? Me ? The User?
    From Development it´s not a very complicated technique but from strategic and law points there are a lot questions about using it.

    ( Reply )
  21. PG

    Jurgenv June 6th

    Well, amazon doesn’t have ‘control’ about which pictures can be uploaded, i guess. You can upload anything but copyrighted material. You will be responsible for what your users upload, but you would be responsible for that too if you’d be using your own server.

    ( Reply )
  22. PG

    Bryan June 6th

    @Ian R-P: PHP5 is required.

    ( Reply )
  23. PG

    Jacob Gube June 7th

    Great tutorial - I’ve been doing this on my site to have an off-site back up of everything. S3 is amazing, highly recommended. Easy to use, clean, always up and it’s a very economical solution to serving static media as well as back-ups.

    Hey Collis - you having any trouble with S3 lately, with the Amazon outages? I’ve been monitoring my site’s performance (read as: “took 5 minutes to click around, not using any special performance tools”), everything looks fine so far.

    ( Reply )
  24. PG

    James Baldwin June 7th

    Not sure if I have been living under a rock or something but hadn’t actually heard of this S3 service - certainly sounds brilliant though and may well be looking into it further! :)

    ( Reply )
  25. PG

    Erik June 8th

    I noticed in the demo that AS3 wants me to download files instead of using my browser’s set behaviour (for images, this would be displaying them directly in the browser; for mp3 files, this would be playing them in winamp). Is that behaviour possible to change?

    ( Reply )
  26. PG

    Nico June 9th

    Very cool. Thank you.

    ( Reply )
  27. PG

    Jurgenv June 11th

    @Erik, not sure. I noticed that too, in some browsers. Right now what I did is just linking to the file, which I thought should do with it whatever it’s supposed to do.

    ( Reply )
  28. PG

    Taylor Satula June 22nd

    Now all we need is for it to be free

    ( Reply )
  29. PG

    How I Did? July 1st

    Great article..Is there a way to select/create sub-folders inside a bucket at the time of uploading the files?

    Regds,
    Deep

    ( Reply )
    1. PG

      Aaron Boushley July 2nd

      You can upload to subfolders / subbuckets / subdirectories, whatever you call them, by appending the additional path info to the beginning of the filename. I had it backwards and was trying to say ‘bucket/my/subfolder’, ‘file.txt’. But you have to say ‘bucket’, ‘my/subfolder/file.txt’.

      ( Reply )
  30. PG

    Mangal July 12th

    Nice article! I will try this one.

    ( Reply )
  31. PG

    trevor July 16th

    I tried this scrip t and it keeps failing on me. i’m pretty sure my awsAccessKey and awsSecretKey are correct.

    anyone have any ideas why this would fail? my php is runnin on a godaddy dedicated sever…

    ( Reply )
  32. PG

    trevor July 16th

    I figured out the issue - if your server cdate and time is way off, this script fails. I corrected the time and now it works.

    That was a needle in a haystack!

    figured i’d save someone else a LOT of time if they have the same problem.

    your error log will say something like: he difference between the request time and the current time is too large…

    ( Reply )
  33. PG

    Windows Themes September 5th

    ok. Is a nice idea and soon I will try it. Thanks!

    ( Reply )
  34. PG

    Brad Hanson September 13th

    For those that were curious about why when using Visser’s script the images download instead of being viewed within the browser:

    When we examine the MetaData of one of these files we can see that the Content-type is set to “application/octet-stream”.

    A quick look into the signature of the function we use,

    public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array())

    We can see that the function takes additional parameters not initially known. The last optional parameter is the one we are looking to modify to change the metadata of uploaded files.

    So modifying the above script to fix this it’s a very simple change:

    f ($s3->putObjectFile($fileTempName, “jurgens-nettuts-tutorial”, $fileName, S3::ACL_PUBLIC_READ, array(), ‘Content-type: ‘.$_FILES['theFile']['type'])) {

    and viola, the images now view as intended.

    Enjoy.

    ( Reply )
    1. PG

      Sr. Muffin May 27th

      what is f? if i replace the above script with the below it creates an error.

      ( Reply )
      1. PG

        Sr. Muffin Happy May 28th

        Sorry i thought this was the S3 PHP class i was changing. it’s just the script from this tutorial. And this does work! Brad is missing the i in front of his if statement though. Also i too had to remove the ‘Content-Type:’. to make it work. But it works! Thanks Brad!

  35. PG

    Pushpesh Singh September 30th

    Hello All,
    A really good and simple tutorial to get anyone up and working with Amazon S3. However, I have a query - how do i change the ‘Content-Type’ of my ‘previously‘ uploaded files which were uploaded with a default ‘Content-Type’?
    Any suggestions?

    Thanks and Regards,

    ( Reply )
  36. PG

    Brent N. Hunter October 16th

    Trevor — you mentioned that you’re using PHP at GoDaddy… I have a question for you or anyone else: I have a website where I am storing all of my files on the S3 service. It’s a Flash-based website to display videos. I need to add a feature to allow users to share a video with someone else… so if they watch a video they like, they click the SHARE button and it asks them for an email address… the user enters an email address and the system sends the URL of the video to the email address that was provided. I understand the way to do this is to call a php script, and the php script would send the email. Any idea how to do this? I don’t believe S3 has php installed but I do have an account at GoDaddy… is there a way to use S3 and GoDaddy in conjunction somehow ? Or better yet, is there a way to do it all on S3?

    Thank you in advance for any help anyone can provide!

    Brent

    ( Reply )
  37. PG

    Brent N. Hunter October 18th

    Please gnore last post, I figured it out, a piece of cake..

    ( Reply )
  38. PG

    Paul October 27th

    Thanks so much - your was REALLLLLY helpful… it saved me so much time and pain!

    ( Reply )
  39. PG

    brian October 30th

    I have wanted to use Amazon’s storage for a while. Thanks for the class it will really help

    ( Reply )
  40. PG

    Matthew Fedak November 17th

    again great tut!

    ( Reply )
  41. PG

    Pranav November 19th

    This is a great tutorial.

    ( Reply )
  42. PG

    captainccs November 22nd

    Brad Hanson:

    I tried your fix to display an image but it still just downloaded. :(

    ( Reply )
  43. PG

    allen December 5th

    Having some trouble with this script…

    Files with spaces fail with an error 505. I’ve been a couple of hours trying to fix this with no luck. The author of the class says to use urlencode, but when I wrap that on $fileName, the browser progress goes for about 5 minutes and then times out, and a file is uploaded but its contents are $fileTempName! The contents of the file is wiped out, and the only thing remaining is the path of the temp file. I’ve tried putting quotes everywhere (including S3.php), putting in a file name with spaces manually, using both the S3.php file included in your zip file and the latest (0.3.7), and I’m still not getting it to work.

    Has anyone gotten this to work file spaces in the file name? It works file on small and large files without spaces! Thanks in advance…

    ( Reply )
  44. PG

    Andy December 13th

    Hello. Great tut!

    I have however run in to some difficulty. I am able to upload small files no problem but when it comes to files about 6mb and over it will upload it to my temp directory and then ask me if I want to save or open page.php!!!

    I have put custom.ini file in to make sure php settings are correct. Even added the php rules to my .htaccess file. We host has said that it is not something they can fix and blame the sctipt……

    Any ideas why it would be doing this???? It’s driving me crazy!!

    Thanks in advance.

    Andy

    ( Reply )
  45. PG

    Andy December 13th

    Sorry that’s meant to say my host says they CANT fix it…..

    ( Reply )
  46. PG

    steffenbew December 22nd

    @captainccs // DISPLAYING IMAGES
    Try to leave out the ‘Content-type:’.-thing. Just: $_FILES['theFile']['type']
    Worked for me.

    @allen // SPACES IN FILENAMES
    Try to urlencode only the $fileName, not the tempname. Just: $fileName = urlencode($_FILES['theFile']['name']);
    Worked for me too. :)

    ( Reply )
  47. PG

    Scott December 30th

    How would I get more information about the file to display at the bottom?

    ( Reply )
  48. PG

    Jason January 12th

    I hate the fact that I am posting here with problems but I just can’t make it work.

    I get “Warning: Invalid argument supplied for foreach() in /srv/www/htdocs/upload/page.php on line 49″

    Which isn’t a big deal. The main problem is that whenever I try to upload an image (tried many file types including jpg, jpeg, gif, etc) I get “Something went wrong while uploading your file… sorry.” With no direction as to where I went wrong.

    I tried creating a new bucket by hand and using it, I even tried letting it create one. It’s not the bucket name cause as soon as it fails I can go and create one with the same name. There is no real error reporting with this class to help me figure it out so I have to post here.

    Any help/guidance would be greatly appreciated.

    ( Reply )
  49. PG

    Kevin January 20th

    I got this to work after changing all the “yourbucket” to my bucket name. Upload speeds are extremely slow, nowhere near 40/KBs. I’m not a programmer, but is there any way to put the download speed and progress of the upload on the page?

    ( Reply )
  50. PG

    Sid February 2nd

    Hey,
    I desparately need your help with this. I am trying to upload a file which is on average 40-50 mb. When I use this tutorial, I get,

    Fatal error: Maximum execution time of 30 seconds exceeded in C:\wamp\www\s3-php5-curl\S3.php on line 1284

    I checked my phpInfo(), with max_execution_time = 30 (both). This is just on my localserver, can I change the setting using ini_set() for my public server?

    Do help.

    ( Reply )
  51. PG

    guiguizmo February 4th

    Hi, i’ve a problem working this code, i have a parse error :

    Parse error: parse error, unexpected ‘)’, expecting ‘(’ in /home/content/my_page.php on line 39

    Is anyone know how to fix it ? Thanks a lot.

    ( Reply )
  52. PG

    Sandeep Kumar Jain March 26th

    I have some movies on S3 server. Now I want to give read permission for some users for some time to access that movies. How can I set access permission to that users who don’t have access key (AWS account). Could you please give me an example for it. I want to set this access policy for some user for some time.

    Thanks

    ( Reply )
  53. PG

    Gerry April 6th

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

    Unless there has been some update to php that I’m unaware of, you might want to change that code as you can’t just put HTML and php side by side link that.

    Nice tutorial btw. I like reading short tutorials where I can skip most of the steps. :)

    ( Reply )
  54. PG

    daniele April 24th

    Unless I want to know if there is any function that allow me to enter into subfolders

    ( Reply )
  55. PG

    Ritwik April 30th

    I followed the steps accurately as specified and is working on Windows. I want to execute the same code on Linux (open suse 10.3) but I am unable to create a bucket - Not getting any message displayed after uploading a file. It neither creates a bucket nor uploads the fileto the bucket.

    ( Reply )
  56. PG

    Vinicius Alves May 12th

    Very great, thank’s

    ( Reply )
  57. PG

    Ghulam Rasool May 17th

    is there any way to create sub-folders inside a bucket

    ( Reply )
  58. PG

    Mr. Loopy May 24th

    Is there anyway to make the file listing get sorted based on last modified date?

    ( Reply )
    1. PG

      Mr Loopy May 25th

      I figured this out. In the $file array you get, you can display $file['time'] and then just use this information to calculate and display the time the file was uploaded, and then use a javascript table sorter to sort the table.

      ( Reply )
  59. PG

    Andrew Slater June 1st

    The amazon stuff confuses me (not a programmer, just doing it when I need to do it…)

    This tutorial was EXACTLY what I needed.

    Any chance you could write one for DevPay / S3 together? I read all over the Amazon site that they’re slightly different if you add DevPay for S3, as well as the DevPay product/lincense etc.

    ( Reply )
  1. Arrow
    Gravatar

    Your Name
    June 1st