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!
- Download the ‘latest beta version (0.2.3)’
- 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.
- 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!



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.
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
# //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. :)
Unless I want to know if there is any function that allow me to enter into subfolders
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.
Very great, thank’s
is there any way to create sub-folders inside a bucket
Is there anyway to make the file listing get sorted based on last modified date?
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.
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.
HI all,
I get that source that work is Ok. But when i run it on ZendFramework platform instead of Amazon S3 of Zend and then get error message below:
Warning: S3::getBucket(): [RequestTimeTooSkewed] The difference between the request time and the current time is too large. in /WWW/reqman/library/AmazonS3/S3.php on line 126
Please help me!!!
Thanks
Maybe a silly question.
When using the S3.php class, is our secret access key passed securely?
Or is it only used on our server to generate a signature that is then passed to the service?
Thanks in advance!
Nice tutorial! thanks
Warning: S3::putObject(): [AccessDenied] Access Denied in /home2/resinmin/public_html/S3/S3.php on line 312
Thanks yar .It helped me a lot
Regards
DileepKumar
This has been very helpful to me. Thanks a lot!
Unfortunately no mention of Copy, which I’m looking for and which can provide rename and move on S3.
Basically I’m looking for a solution for file names more than 255 characters, which I can not create on my Linux servers. So the solution I thought is to put/rename(copy to temp with another name-delete original-copy back to original)
My bad…in the above post I said that this class doesn’t support copy BUT IT DOES SUPPORT COPY. It’s just that this tutorial doesn’t talk about it.
m a late comer to AWS but thanks a lot for this super awesome tutorial..
Warning: S3::putBucket(freeworkouts.discountworkouts.com): [RequestTimeTooSkewed] The difference between the request time and the current time is too large. in C:\xampp\htdocs\sources\sources\S3.php on line 188
Warning: S3::putObject(): [RequestTimeTooSkewed] The difference between the request time and the current time is too large. in C:\xampp\htdocs\sources\sources\S3.php on line 312
Something went wrong while uploading your file… sorry.
Help ME:
Please select a file by clicking the ‘Browse’ button and press ‘Upload’ to start uploading your file.
All uploaded files
Warning: S3::getBucket(): [RequestTimeTooSkewed] The difference between the request time and the current time is too large. in C:\xampp\htdocs\sources\sources\S3.php on line 126
Warning: Invalid argument supplied for foreach() in C:\
where the problem is occured?
I got a question…. I’ve been hacking away at this problem for what seems to be FOREVER!!!
here is the code
—————————————————————–
$fileID=(my orignal file name)
$uri=”" // i stilll have no idea what this uri is…. but i concluded that it is the path thats relative the the bucket root.
//this S3 code does not work for me….. I don’t know why… gives me a fopen($fileID) error..
$fp = fopen(“$fileID”, “wb”);
if (($object = $s3->getObject($bucket, $uri, $fp)) !== false) {
print_r($object);
}
/*
I’m trying to grab the file from S3′s server, channel it into my server and output it as a Force Download, more less what I’m really after is the renaming ability i can achieve with a Force Download.
EX: (http://…../myfile.xyz) downloaded as (filenumber2-121809.zip)
*/
/*
this part of the script is my original download script and it work fine pulling the S3′s http URL this is what im using right now and having trouble with.
*/
header(‘Content-Description: File Transfer’);
header(‘Content-Type: application/octet-stream’);
header(‘Content-Disposition: attachment; filename=’.$filename);
header(‘Content-Transfer-Encoding: binary’);
$expires = 60*60*24*14;
header(“Pragma: public”);
header(“Cache-Control: maxage=”.$expires);
header(‘Expires: ‘ . gmdate(‘D, d M Y H:i:s’, time()+$expires) . ‘ GMT’);
header(‘Content-Length: ‘ . filesize($URL));
ob_clean();
flush();
readfile($URL);
————————————————————-
so where do i go from here?
:::: The PROBLEM ::::
There is a format that seems to be having issues once downloaded, and in process to open. A QuickBooks format.
I’ve also noticed that with this download script, the file-size increases by 1kb… i don’t think thats natural, is it?
seems like some where in this script there is data that is not being read or something, so in turn corrupts the quick book file?? once downloaded the QB file loses its meta-data in telling which version of QB it was made.
I tested zipping the file, uploading, downloading, unzipping, and it work just fine. so it cant be my upload script, its gotta be my download script, right?
maybe…. so i tested downloading the file straight from S3′s server. and it work just fine, so i concluded that it has to be the download script. but what part?
Could anyone enlighten me on whats wrong with my force download?
thanks for any help ahead of time!!
Hey cvue,
This doesn’t directly answer your question, but it might give you what you’re after.
When you upload files to S3, you can specify meta information as well. So in your S3 upload script, just specify “Content-disposition: attachment; filename=filename.ext”.
Best of luck.
Hello guys, I’m using this script and is working pretty nice. Now going back on the discussion about displaying the images in the browser… I got it work adding the Content-type.
Now my question is:
Should I use:
“Content-disposition: attachment; filename=filename.ext”
or specify the content-type:
“Content-type: image/gif”
In fact… both work. In my script I prefer to use the first one, It’s going to be hard for me to get the content-type of some files in my uploader and I don’t trust in PHP until we get PHP 5.3 with fileinfo.
Can anyone explain me which way is better and why?
Thanks!
Hey nice script….works perfectly for me…….thanks dude!!!
Is this script capable of large files up to 2GB ? Means where i can set/increase the limit ?
I am using this script and i have faced a problem while uploading large file that when file upload is completed to PHP TMP DIRECTORY site does not get any response
if($s3->putObjectFile($fileTempName, “sembled”, $fileName, S3::ACL_PUBLIC_READ))
{
echo ‘success’; //this line is not executed
}
Although file successfully goes to amazon and site coutinues to waiting for response. please reply me if any one knows this issue how to solve
I would like to know how to upload a file to my Amazon s3 using your class without using a form and a file path. Instead I already have the file loaded as in $file = file_get_contents(“hi.jpg”);
The reason why I want to know how to do it this way is because I’m receiving the image from an external source, not on my local machine. The image is actually coming from a flash application to my server as a base64 string, then I base64 decode it back into a byteArray and it’s ready for action but I do not know how to do it this way.
The tutorial was great, and the code works wonderfully – thank you.
I was wondering whether you had a similar tutorial of how to delete a file from the bucket?
What about if you want to mix elements together? I want to make a form that sends the uploaded file to S3 but stores the values of the other fields to a DB for use later.
Can a separate page be made to handle the form actions to keep the page with the form clean in the code area?
How can I amend the max file size?
I need mine to be able to upload more than my PHP filesize limit
The tutorial was great, code works perfectly – thank you.
But I have problem when I upload large files it gives me timeout or sometime no respond I am using
S3::$useSSL = false; WITH S3::getHttpUploadPostParams function
Please help me how I can upload 2 GB files with these functions easily ?
Thanks
Hello,
First of all I’d like to congratulate you for this step by step tutorial. Secondly, after I finished reading it and tried to run page.php I end up having this error:
faultCode0faultStringWarning:S3::getBucket(): [RequestTimeTooSkewed] The difference between the request time and the current time is too large. in /home/aarregui/public_html/s3video/S3.php on line 126faultCode0faultStringWarning:Invalid argument supplied for foreach() in /home/aarregui/public_html/s3video/page.php on line 49
Do you think you could help me with that? Am I doing something wrong?
Thank you.
Thanks to the Good article.
Hello
How can I create a new Bucket with PHP?
Hi there!
How can I check connection with S3 server before upload file?
With using this class of course.
tnx.
What’s the bandwidth consumption like on a script like this and are there any issues with the PHP script timeout (which on most hosts are set to something like 15-30seconds)? Surely uploading a 100mb file is going to take longer than 15-30seconds and just timeout?
M.
I keep gettting the “Something went wrong while uploading your file… sorry.” message and I’m not sure what I’m doing wrong.
I changed “yourbucket” to the name of my bucket and I put in the access keys.
I don’t understand why use the tag for html5 and use different kinds of video encoding and even add extra code when you can just use flash?
Nice article… Thanks
Is it possible to have users delete a file? Ideally, a “delete” link will be next to each file that when clicked, will delete the file. Is that possible? If so, what would the code look like?
The fix that worked for me with the following errors:
Warning: S3::getBucket(): [RequestTimeTooSkewed] The difference between the request time and the current time is too large
I had to change the server settings to stop pulling the date automatically from the internet and instead manually enter the date time. I am running a VM and am not sure why this would occur but had this update allow the script to execute.
Amazing tutorial, very well documented, worked like a charm, thanks!!
Great script!
There have been many questions on this forum regarding the below error:
Warning: S3::getBucket(): [RequestTimeTooSkewed] The difference between the request time and the current time is too large
Here is the URL to read up on the error:
http://www.bucketexplorer.com/documentation/amazon-s3–difference-between-requesttime-currenttime-too-large.html
I am use your code then i upload the video 1mb video is successfully upload but i upload 3mb i get this warning
Warning: S3::inputFile(): Unable to open input file: in /home/myappdemo/myappdemo.com/myadvisory/S3.php on line 224
Something went wrong while uploading your file… sorry.
I can’t understand wat i means plz help me…..
Nice article, so much helpful….
Thanks
Nice Tutorial,
I have a question about pulling information from S3′s bucket.
Is there a way to get a specific file from the bucket, using the prefix stuff in the S3.php class ? My image folder on S3 is massive and the my bandwidth is not so fast.
So pulling the entire bucket slows my site down alot.
:)
I can create sub folder from the aws s3 console, but I can’t find how to create folder by this sdk. I can upload a file to the bucket and sub folder by this code after I create a sub folder at aws console, so can anyone can share the code of create sub folder?
Thanks.
I can create sub folder by aws console, but how can I create it from this sdk? I also can upload a file to the bucket’s sub folder after I create this sub folder from aws console. Can anyone share the code to create a sub folder use this sdk of php?
Thanks.
@Jadamster:
If you know the path in the bucket, you can download the file individually, for example:
$s3->getObject(‘mybucket’, $uploadName, fopen(‘savefile.txt’, ‘wb’));
—-
@ives:
It automatically creates the folder(s) if you specify a path with folders in it, for example:
$s3->putObject($s3->inputResource(fopen($filename, ‘rb’), filesize($filename)), ‘mybucket’, ‘subfolder/’ . $filename, S3::ACL_PUBLIC_READ, array(), array(), S3::STORAGE_CLASS_RRS);
I’m not sure how to delete folders programatically however.
—-
Btw, it could be better to point to the Github repo of the library (as location to download from) than the 2007 blog post:
https://github.com/tpyo/amazon-s3-php-class
The demo comes up with a 404 error :o(
Quick question
My S3 Server will have a ton of files on it, and many will share the same name
When I want to pull a specific file from the server, I access it via hash
But, when I want to delete a file from the server, it appears you can only delete it by file name.
If I try to delete a file by file name, wouldn’t that in turn delete every single file in the bucket that shares the same name?
If so, isn’t there a way to delete a file on the server by hash to avoid this problem?
Thank you for your time
I use the hash method as well to avoid filename collisions on Bighugefile.com. I accomplish this by renaming the uploaded file file to “[hash]/[filename]“, and then uploading it to S3 via putObjectFile(). This way, S3 actually sees the filename as “[hash]/[filename]“. Adding the “/” between the hash and the original filename causes S3 to treat this as folder/file, with the hash being the unique folder name. This allows me to preserve the original filename while maintaining a unique hashed structure. When I get ready to delete the file(s), I simply pass “[hash]/[filename]” as the filename to the S3 deleteObject() call. This deletes both the hashed folder and the original file. I hope this makes sense.
Sorry, please disregard my last comment. I was on about 2 hours of sleep when I made it.
Obviously you can’t have multiple files of the same name in the same bucket, that’s just silly
Thanks
When i browse to http://mybucket.s3.amazonaws.com/page.php the browser is asking for downloading the file!!????
How do you “run” the file?
NO ONE has this problem??
Hello,
Amazon S3 do not manage php files.
It is NOT a php server.
S3 only serve static files (.html)
Regards
Dimitri