Created
July 20, 2016 14:53
-
-
Save mikefrey/841339fd18d3e9344243479d14491bf4 to your computer and use it in GitHub Desktop.
Angular S3 browser upload with hapi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
plugin: { | |
register: './app/plugins/s3-upload-token', | |
options: { | |
accessKey: 'YOURACCESSKEY', | |
secretKey: 'YOURSECRETKEY', | |
photoBucket: 'YOURBUCKET', | |
s3Policy: { | |
expiration: 10 * 60 * 1000, // 10 min | |
conditions: [ | |
{'acl': 'public-read'}, | |
['starts-with', '$key', 'uploads/'], | |
['starts-with', '$filename', 'uploads/'], | |
['starts-with', '$Content-Type', ''], | |
['content-length-range', 0, 5242880] | |
] | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Angular 1.x service for uploading to S3 | |
angular.module('ngS3upload', []). | |
service('S3Uploader', function($http, $q) { | |
this.uploads = 0 | |
const self = this | |
this.getUploadOptions = function(uri) { | |
return $q((resolve, reject) => { | |
$http.get(uri) | |
.success(response => resolve(response)) | |
.error(error => reject(error)) | |
}) | |
} | |
this.upload = function(uri, key, acl, type, accessKey, policy, signature, file) { | |
const deferred = $q.defer() | |
const fd = new FormData() | |
fd.append('key', key) | |
fd.append('acl', acl) | |
fd.append('Content-Type', file.type) | |
fd.append('AWSAccessKeyId', accessKey) | |
fd.append('policy', policy) | |
fd.append('signature', signature) | |
fd.append('file', file) | |
const xhr = new XMLHttpRequest() | |
xhr.upload.addEventListener('progress', uploadProgress, false) | |
xhr.addEventListener('load', uploadComplete, false) | |
xhr.addEventListener('error', uploadFailed, false) | |
xhr.addEventListener('abort', uploadCanceled, false) | |
// Define event handlers | |
function uploadProgress(e) { | |
if (typeof deferred.notify !== 'function') return | |
let progress = 'unable to compute' | |
if (e.lengthComputable) { | |
progress = Math.round(e.loaded * 100 / e.total) | |
} | |
const msg = { type: 'progress', value: progress } | |
deferred.notify(msg) | |
} | |
function uploadComplete(e) { | |
const xhr = e.srcElement || e.target | |
self.uploads-- | |
if (xhr.status === 204) // successful upload | |
return deferred.resolve(xhr) | |
deferred.reject(xhr) | |
} | |
function uploadFailed(e) { | |
const xhr = e.srcElement || e.target | |
self.uploads-- | |
deferred.reject(xhr) | |
} | |
function uploadCanceled(e) { | |
const xhr = e.srcElement || e.target | |
self.uploads-- | |
deferred.reject(xhr) | |
} | |
// Send the file | |
this.uploads++ | |
xhr.open('POST', uri, true) | |
xhr.send(fd) | |
return deferred.promise | |
} | |
this.isUploading = function() { | |
return this.uploads > 0 | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// hapi.js plugin for generating a S3 upload token | |
'use strict' | |
const _ = require('lodash') | |
const crypto = require('crypto') | |
exports.register = function(server, options, next) { | |
server.route({ | |
method: 'GET', | |
path: '/api/s3/uploadtoken', | |
config: { | |
handler: function(request, reply) { | |
let policyDoc = _.clone(options.s3Policy) | |
policyDoc.expiration = new Date(Date.now() + policyDoc.expiration).toISOString() | |
policyDoc.conditions.push({ bucket: options.photoBucket }) | |
let policy = new Buffer(JSON.stringify(policyDoc)).toString('base64') | |
let hmac = crypto.createHmac('sha1', options.secretKey) | |
hmac.update(policy) | |
let signature = hmac.digest('base64') | |
reply({ | |
key: options.accessKey, | |
bucket: options.photoBucket, | |
policy: policy, | |
signature: signature | |
}) | |
} | |
} | |
}) | |
next() | |
} | |
exports.register.attributes = { | |
name: 's3-upload-token', | |
version: '1.0.0' | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment