Quiet the old question but it did help me a bit to get it finally done.
My solution is based on PHP and JavaScript with jQuery.
I have the entire solution nicely wrapped at https://github.com/JoernBerkefeld/s3SignedUpload but here are the essentials:
api.php:
<?php
require_once '/server/path/to/aws-autoloader.php';
use AwsCommonAws;
$BUCKET = "my-bucket";
$CONFIG = "path-to-iam-credentials-file-relative-to-root.php"
function getSignedUrl($filename, $mime) {
$S3 = Aws::factory( $CONFIG )->get('S3');
if(!$filename) {
return $this->error('filename missing');
}
if(!$mime) {
return $this->error('mime-type missing');
}
$final_filename = $this->get_file_name($filename);
try {
$signedUrl = $S3->getCommand('PutObject', array(
'Bucket' => $BUCKET,
'Key' => $this->folder . $final_filename,
'ContentType' => $mime,
'Body' => '',
'ContentMD5' => false
))->createPresignedUrl('+30 minutes');
} catch (S3Exception $e) {
echo $e->getMessage() . "
";
}
$signedUrl .= '&Content-Type='.urlencode($mime);
return $signedUrl;
}
echo getSignedUrl($_GET['filename'],$_GET['mimetype']);
please make sure to add user authentication to your api.php. Else everyone who knows the path to that file could upload files to your bucket.
credentials.inc.php:
<?php
return array(
'includes' => array('_aws'),
'services' => array(
'default_settings' => array(
'params' => array(
'key' => 'MY-ACCESS-KEY',
'secret' => 'MY-SECRECT',
'region' => 'eu-west-1' // set to your region
)
)
)
);
client.js:
$("input[type=file]").onchange = function () {
for (var file, i = 0; i < this.files.length; i++) {
file = this.files[i];
$.ajax({
url : s3presignedApiUri,
data: 'file='+ file.name + '&mime=' + file.type,
type : "GET",
dataType : "json",
cache : false,
})
.done(function(s3presignedUrl) {
$.ajax({
url : s3presignedUrl,
type : "PUT",
data : file,
dataType : "text",
cache : false,
contentType : file.type,
processData : false
})
.done(function(){
console.info('YEAH', s3presignedUrl.split('?')[0].substr(6));
}
.fail(function(){
console.error('damn...');
}
})
}
};
s3 cors settings (PUT & OPTIONS are actually needed, but cannot enable OPTIONS directly...):
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…