This is the directive I like to use for my file uploads:
https://github.com/danialfarid/angular-file-upload
You can install it with bower: bower install ng-file-upload --save
It comes with many features like progress bar handling and easy drag and drop.
You can find examples on how to use it on the github link, but here's how I use it in Coffeescript with AWS S3 direct upload. Just note that doing uploads to s3 takes a whole lot more of code. That also includes generating a token from the server.
Thats the /api/media/upload_token
you see there.
$scope.processUpload = (metadata) ->
$scope.fileUploads.push metadata
$http.put('/api/media/' + metadata._id, metadata)
.success (res) ->
// do your stuff here when the upload is finished
// $scope.reloadMedia();
console.log metadata
$scope.onFileSelect = ($files) ->
# merge new uploads, ignore old uploads
$scope.files = $files;
$scope.upload = [];
# create a new closure for each file upload
for file, i in $files
file.progress = parseInt 0
do (file, i) ->
anticache = Math.random().toString(36).substring(3,9)
$http.get('/api/media/upload_token?mimeType=' + file.type + '&rnd=' + anticache,
{filename: file.name})
.success (response) ->
s3Params = response
uploadData =
url: 'https://<mybucketname>.s3.amazonaws.com/'
method: 'POST'
data:
key: s3Params.filename + '$$' + file.name
acl: 'public-read'
'Content-Type': file.type
AWSAccessKeyId: s3Params.AWSAccessKeyId
success_action_status: 201
Policy: s3Params.s3Policy
Signature: s3Params.s3Signature
file: file
# start the upload
$scope.upload[i] = $upload.upload(uploadData)
.progress (evt) ->
file.progress = parseInt(100.0 * evt.loaded / evt.total)
.success (res, status, headers, config) ->
file.progress = parseInt 100
if status is 201
xmlDoc = (new DOMParser).parseFromString(res, 'application/xml')
getXmlValue = (k) -> xmlDoc.getElementsByTagName(k)[0].firstChild.nodeValue
metadata =
_id: response.filename
location: getXmlValue 'Location'
bucket: getXmlValue 'Bucket'
key: getXmlValue 'Key'
etag: getXmlValue 'ETag'
filename: file.name
$scope.processUpload(metadata)
else
throw new Error("File Upload Failed! Server status is not 201");
alert 'Upload Failed, please try again.'
This is my Jade view, just note that the classes I have are from Bootstrap
.form-group.well(ng-file-drop='onFileSelect($files)')
span.btn.btn-primary.btn-file.btn-block
| Upload Media
input(type='file', ng-file-select='onFileSelect($files)', multiple)
p.help-block You can also drag and drop files here.
.row(ng-repeat='file in files')
.col-md-8
.progress
.progress-bar(role='progressbar', style='width:{{file.progress}}%;')
| {{file.name}} : {{file.progress}}
.col-md-4
button.btn.btn-warning(type='button', ng-click='abort($index)', ng-show='file.progress != 100') Abort
div(ng-file-drop-available='dropSupported=true', ng-show='!dropSupported') HTML5 Drop File is not supported!