This class is a standalone Amazon S3 REST implementation for PHP 5.2.x (using CURL), that supports large file uploads and doesn’t require PEAR.
Download source: (view changelog)
- Download latest development version (0.5.x – recommended)
- Download old stable version (0.4.0 – 20th Jul 2009)
Usage: See the class documentation and example.php in the source distribution.
Known Issues:
- Files larger than 2GB are not supported on 32 bit systems due to PHP’s signed integer problem
- SSL is enabled by default and can cause problems with large files. If you don’t need SSL, disable it with S3::$useSSL = false;
More Information:
- Amazon S3 documentation
How to Use Amazon S3 & PHP to Dynamically Store and Manage Files with Ease- Building a Small Business Backup System Using Amazon S3
NOTE ON FOLDERS: Amazon S3 does not support folders. Clients like S3Fox create specific files that are displayed as folders. Just use slash paths for your object names (foo/bar.txt) and (foo/) as your prefix when listing contents.
Amazon S3™ is a trademark of Amazon.com, Inc. or its affiliates.
Hey Don,
Just wanted to thank you for this great code. It’s exactly what I need and nothing more.
Keep up the good work!
The class seems to be updated with some of the suggestions here. So downloading the latest version will do the job without the need for any modifications. I am glad i came across it,thank you so much.
This class does not support using french characters.
When trying to copy from a folder called “Àbcdefg” I get an invalid signature error
However, the same action from the folder “Abcdefg” and “abcdefg” work perfectly fine
Try using UTF-8.
Don, I just wanted to thank you for this. It Just Works™. Perfect!
Hi,
I have the same problem of Troy. Here the detail:
A PHP Error was encounteredSeverity: User Warning
Message: S3::putObject(): [55] select/poll returned error
Filename: libraries/S3.php
Line Number: 410
A PHP Error was encountered
This error appears randomly and now more and more often (the class has worked correctly for me for six moths).
I use ubuntu server 7.04, php 5.2.3 and the last class version. The uploaded files are about 70kb-700kb.
Any idea to solve my issue?
Ty in advance!!
Lua.
I too am also getting this issue and am wondering how to solve it.
Looks like updating curl itself might help, it help fix this issue for me at least
This is a great bit of code, thank you. The only slight issue I came across (as mentioned by some other respondents) was that bucket names get cast to lowercase meaning that it can never find an AWS bucket that uses mixed or all upper case.
But the code is great. Thanks for sharing!
This was changed in the master branch… According to the API docs bucket names were never meant to include uppercase characters, but for some reason it was allowed.
Did anyone get a chance to look into my comment.
Please help. How to use prefix with getBucket method.
contents = $s3->getBucket(‘bucketName’, ‘this/folder’);
Bucket location in S3: /bucketName/this/folder
Thanks,
Mike
Great work thank you.
Can i get all the folder names inside the bucket and also all the files inside particular folder.
I have tried to use getBucket() method with prefix option, But could not succeed.
$contents = $s3->getBucket(‘bucketName’,, ‘this/folder’);
Please let me know.
Thanks,
Mike
This is a great class!
Very useful to me and my requirements, thanks to share it!
this is really great script. Thanks webmaster.
A cheap hack for everyone trying to get reduced redundancy to work:
Insert:
$rest->setAmzHeader(‘x-amz-storage-class’ , ‘REDUCED_REDUNDANCY’);
below the
$rest->setAmzHeader(‘x-amz-acl’, $acl);
in the bottom of the putObject function
An (undocumented) RRS option for putObject() is available in the dev branch on github.
Hi!
There’s bug in getBucket() method.
If 0 is passed to this method as @maxKeys parameter, do while loop will circle until memory_limit or max_execution_time is reached.
This is how we fix it:
public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null, $delimiter = null, $returnCommonPrefixes = false) {
if ($maxKeys == 0) return true;
Cheers!
Code Igniter / S3.php Library bug FIXED:
The fix to my previous post on 28th Apr 2011 is as follows:
Change:
$s3 = new S3( AMZ_AWS_ACCESS_KEY, AMZ_AWS_SECRET_KEY );
To:
$this->s3->S3( AMZ_AWS_ACCESS_KEY, AMZ_AWS_SECRET_KEY );
Reason:
When CI Library classes extend tot he core CI_Controller class.
Hope this saves someone time.
Richard
Thoughts on why S3 Keys are not authenticating. Getting this error back from S3: [InvalidAccessKeyId] The AWS Access Key Id you provided does not exist in our records.
Overview: Added the s3.php class into CodeIgniter Libraries and modified all instance of class name to My_S3. Class seems to be working. When calling any function in teh class I get the above Access Key warning. Sample code below:
$s3 = new S3( AMZ_AWS_ACCESS_KEY, AMZ_AWS_SECRET_KEY );
$bucket_list = $this->s3->listBuckets( true );
Verified the Access Key and Secret Key are working using other tools such as Panic Transmit S3 protocol and SFox for FireFox.
Using SC Class 0.4.0 – $Id: S3.php 47 2009-07-20 01:25:40Z don.schonknecht $
Where should I look for the bug?
Thanks Richard
Hi,
Firstly excellent Class, worked first time, so thankyou very much!
I am having a issue (that i dont think is due to the class) with intermittent connection problems and was wondering whether anybody experienced this?
I get the Warning:
PHP Warning: S3::putObject(): [7] couldn’t connect to host in /libraries/S3/S3.php on line 358
As said this doesnt happen all the time, it seems to be random, does anyone have any ideas? I would have thought that S3 was highly available so the cant connect to host doesnt really make sense!
Thanks,
Jeff
Hi am am fairly new to PHP and I am trying to generate a temporary autheticated URL for Amazon S3, using your S3 PHP class and the method below suggested by Wilson Mattos, but I keep getting:
Fatal error: Call to undefined function add_action() in F:\wamp\www\test\S3.php on line 50
Any clue to what I may be doing wrong? And thank you for your time and effort in developing this.
<?php
$S3AWSID=’ACCESS_KEY_ID’;
$S3AWSSECRET=’SECRET_ACCESS_KEY’;
require_once ‘S3.php’;
$s3 = new S3(“$S3AWSID”, “$S3AWSSECRET”);
?>
<?php echo $s3â€>getAuthenticatedURL(“BUCKET”, “FILE”, EXPIRE_TIME); ?>
Thank you.
Thanks for info
Thank your for your really helpful class – it works great!
@Mind: If you are located in Europe, you should try “s3-external-3.amazonaws.com” instead of “s3.amazonaws.com”
i get this error today after many month i use backup:
PHP Warning: S3::listBuckets(): [6] Couldn’t resolve host ‘s3.amazonaws.com’ in S3.php on line 90
i can’t understand why…can u help me?
Thanks a lot for this.
However I found that the Content-Type would not be set correctly. I tried various things and couldn’t figure it out then decided to make some changes in the class:
In your function function putObject I added this line:
<span class="source-variable">$input['type'] = self::getMimeType_new_from_jim(<span class="source-variable">$uri);Just before this line:
if (!isset(<span class="source-variable">$input['type'])) {Then at the bottom just before the final } I added this:
public static function getMimeType_new_from_jim(<span class="source-variable">$file) {
static <span class="source-variable">$exts = array(
'jpg' => 'image/jpeg',
'gif' => 'image/gif',
'png' => 'image/png',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'ico' => 'image/x-icon',
'swf' => 'application/x-shockwave-flash',
'pdf' => 'application/pdf',
'zip' => 'application/zip',
'gz' => 'application/x-gzip',
'tar' => 'application/x-tar',
'bz' => 'application/x-bzip',
'bz2' => 'application/x-bzip2',
'txt' => 'text/plain',
'asc' => 'text/plain',
'htm' => 'text/html',
'html' => 'text/html',
'css' => 'text/css',
'js' => 'text/javascript',
'xml' => 'text/xml',
'xsl' => 'application/xsl+xml',
'ogg' => 'application/ogg',
'mp3' => 'audio/mpeg',
'wav' => 'audio/x-wav',
'avi' => 'video/x-msvideo',
'mpg' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'mov' => 'video/quicktime',
'flv' => 'video/x-flv',
'php' => 'text/x-php'
);
<span class="source-variable">$ext = split("[/\\.]", <span class="source-variable">$file) ;
<span class="source-variable">$n = count(<span class="source-variable">$ext)-1;
<span class="source-variable">$ext = <span class="source-variable">$ext[<span class="source-variable">$n]; // <span class="source-variable">$ext is now the file extension
if (isset(<span class="source-variable">$exts[<span class="source-variable">$ext])) {
return <span class="source-variable">$exts[<span class="source-variable">$ext];
} else {
return 'application/octet-stream';
}
}
It works well for me. I release the above code to the public domain free for all to use.
@Stefan:
To me the original Amazon PHP SDK seems too bloated. And it’s autoloader conflictet with that of my framework. So why use such a beast if there’s a lean class like this?
Hi all!
Im’ new to S3.
Please let me ask a stupid question.
This class seems to exist quite a long time now.
Perhaps it was written at a time when Amazon had no PHP API?
Why don’t you all use the Amazon PHP API?
(http://aws.amazon.com/sdkforphp/)
Is it not as easy to use as this one?
Thanks for your coments!
Thank you so much for this class.
I don’t know how I could have ever fulfilled my client’s expectations for backup to S3 unless I had a pre-written class.
Much Gratitude!
…Burton
It’s great.Thank you very much!
Sorry, but the site documentation doesn’t explain this clearly, so I hope you can excuse my ignorance.
I’m testing using S3 as a remote backup for critical files on a PHP application. I’m developing in Wamp (Win XP). When I try to run your example.php sample, I got the [60] error about no certificates.
I want to use SSL, so I’ve downloaded the cert & key generated by the Amazon control panel (cert-****.pem & pk-****.pem), and then add the instructions to getResponse():
if (S3::$useSSL) {
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1);
// New lines
// Certificate & key file in pem format
curl_setopt($curl, CURLOPT_SSLCERT, S3::$certFile);
curl_setopt($curl, CURLOPT_SSLKEY, S3::$pkeyFile);
// End new lines
}
but the error persists.
On the other side, downloading a Certificates bundle from the curl site and adding the next line instead works:
// CA bundle file
curl_setopt($curl, CURLOPT_CAINFO, “C:\wamp\www\s3\certs\cacert.pem”);
I think that the certificate is obtained automatically and verified against a root certificate present in the bundle, so it works. Still, why wasn’t the first option successful?
Shouldn’t CURLOPT_SSLCERT bean an inmediate aceptance? Or are those certificates mean’t for other things, and the ssl is using the generic amazon certificate for *.s3.amazonaws.com.
That would explain why it worked like that, and yet, what are the those cert and key for?
Hi there, how can I bulk upload files in a directory to my s3 bucket?
Can I just get all file names from the directory and put it in to an array, then use the putObject() to upload?
This class is awesome, use it all the time.
It would be great if it was updated with the invalidation and default-object features amazon has added lately.
First off, thanks so much for this class. Works like a dream.
Quick question though, every time I try to use the prefix option on getBucket I get a SignatureDoesNotMatch error.
$contents = $s3->getBucket(“bucket”) – works
$contents = $s3->getBucket(“bucket”, “a”); – error
Warning: S3::getBucket(): [SignatureDoesNotMatch] The request signature we calculated does not match the signature you provided. Check your key and signing method. in /Applications/MAMP/htdocs/assets/classes/S3.class.php on line 126I’ve tried urlencoding different things and also sorting headers lexicographically. I just can’t seem to get it down. Any ideas?
I like the profuseness of the comments.
But,
it seems that this class doesn’t support bucket names with capital letters, even though S3 will treat two buckets such as ‘SomeBucket’ and ‘somebucket’ as distinct, and will let them coexist as separate entities.
If a user tries something like $s3->putBucket(‘SomeBucket’);
a bucket with a name of ‘somebucket’ will created in S3.
If a user has created a bucket with a name of ‘SomeBucket’ via some other means (like the AWS Management Console), it will be inaccessible with this class.
@Jaka,
Yes – I’m busy with a rewrite that will. But if you don’t like it, use something else
This is really poorly designed.
All the objects share a single pair of credentials. They don’t behave as you would expect objects to behave at all.
I found the solution… You have to urlencode() the object’s name
If ther’s a backslash in the path of an object (not a slash which separates folders) then copyObject fails with ” The request signature we calculated does not match the signature you provided.”. A minor problem, and I’m looking into fixing it, but if anyone has a suggetion… Thanks.
When I pass a short string to putObject it takes minutes to complete. The same data passed in a file completes immediately.
Slow:
$data = “0123456789\n”;
$put = $s3->putObject($data, $bucket, $path, S3::ACL_PUBLIC_READ);
Fast:
$data = $s3->inputFile(“file.txt”);
$put = $s3->putObject($data, $bucket, $path, S3::ACL_PUBLIC_READ);
Hi,
I have to transfer my files from amazon s3 to my new sever . My bucket has large number of images and videos. Is it possible to transfer all my files to my new server using php script ?
Thanks in Advance,
Anoop
Hey Bro Thank you very much, among the libraries out there I think yours is the best. Its simple and has nice documentation and example good enough for me…
Just wanted to say thanks for this class and also curious as to if you have plans to update it to manage the recent bucket policy additions to S3. Thanks again.
@Frank Koehl: The API has not changed very much at all since the last update, with the exception of S3′s recently released RRS feature. If there’s a big demand for it I’ll pester Don to update the code
The code as it stands is quite stable and easy to use.
I was having a hard time getting this class to let me create buckets in the US West or Asia Pacific regions. The location string for US West is “us-west-1″ and the location string for Asia Pacific is “ap-southeast-1″. Then you have to edit one line in this class due to Amazon being case sensitive:
Line 213:
$locationConstraint = $dom->createElement(‘LocationConstraint’, strtoupper($location));
becomes:
$locationConstraint = $dom->createElement(‘LocationConstraint’, $location);