Skip to content

Instantly share code, notes, and snippets.

@zxbodya
Last active April 6, 2024 03:40
Show Gist options
  • Star 37 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save zxbodya/3cdabd9172bcc89f8ac5 to your computer and use it in GitHub Desktop.
Save zxbodya/3cdabd9172bcc89f8ac5 to your computer and use it in GitHub Desktop.
Client side uploads to s3, with pre-signed upload form (PHP/JS)
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
public function getImageUploadForm($key, $expiration, $sizeLimit)
{
$policy = [
'expiration' => (new \DateTime($expiration))->format("Y-m-d\TH:i:s") . ".000Z",
'conditions' => [
['bucket' => $this->awsBucket],
['acl' => 'private'],
['key' => $key],
['Content-Type' => 'image/jpeg'],
["content-length-range", 0, $sizeLimit]
]
];
$policyJson = json_encode($policy);
$policyBase64 = base64_encode($policyJson);
$signature = base64_encode(hash_hmac('sha1', $policyBase64, $this->awsSecret, true));
$form = [
'key' => $key,
'AWSAccessKeyId' => $this->awsKey,
'acl' => 'private',
'policy' => $policyBase64,
'signature' => $signature,
'Content-Type' => 'image/jpeg',
];
return $form;
}
public function getUploadUrl()
{
return $this->s3client->getObjectUrl($this->awsBucket, '');
}
// url from getUploadUrl in file above
// data presigned upload form data getImageUploadForm in file above
// file - File or Blob to be uploaded
// fileName - filename which would be passed with upload form (does not matter in case of s3)
function upload(url, data, file, fileName){
var xhr = new XMLHttpRequest();
xhr.onerror = function (e) {
// handle failture
};
xhr.upload.addEventListener('progress', function (e) {
// handle notifications about upload progress: e.loaded / e.total
}, false);
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status >= 200 && xhr.status <= 299) {
// upload completed
} else {
// failed with error messge from server
}
}
};
function formData(data, file, fileName) {
var res = new FormData();
for (var k in data) {
res.append(k, data[k]);
}
res.append('file', file, fileName);
return res;
}
xhr.open('POST', url, true);
xhr.send(formData(data, file, fileName));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment