MEAN Stack File uploads
I recently did something just like this. I used angular-file-upload. You'll also want node-multiparty for your endpoint to parse the form data. Then you could use s3 for uploading the file to s3.
Here's some of my [edited] code.
Angular Template
<button> Upload <input type="file" ng-file-select="onFileSelect($files)"></button>
Angular Controller
$scope.onFileSelect = function(image) { $scope.uploadInProgress = true; $scope.uploadProgress = 0; if (angular.isArray(image)) { image = image[0]; } $scope.upload = $upload.upload({ url: '/api/v1/upload/image', method: 'POST', data: { type: 'profile' }, file: image }).progress(function(event) { $scope.uploadProgress = Math.floor(event.loaded / event.total); $scope.$apply(); }).success(function(data, status, headers, config) { AlertService.success('Photo uploaded!'); }).error(function(err) { $scope.uploadInProgress = false; AlertService.error('Error uploading file: ' + err.message || err); });};
Route
var uuid = require('uuid'); // https://github.com/defunctzombie/node-uuidvar multiparty = require('multiparty'); // https://github.com/andrewrk/node-multipartyvar s3 = require('s3'); // https://github.com/andrewrk/node-s3-clientvar s3Client = s3.createClient({ key: '<your_key>', secret: '<your_secret>', bucket: '<your_bucket>'});module.exports = function(app) { app.post('/api/v1/upload/image', function(req, res) { var form = new multiparty.Form(); form.parse(req, function(err, fields, files) { var file = files.file[0]; var contentType = file.headers['content-type']; var extension = file.path.substring(file.path.lastIndexOf('.')); var destPath = '/' + user.id + '/profile' + '/' + uuid.v4() + extension; var headers = { 'x-amz-acl': 'public-read', 'Content-Length': file.size, 'Content-Type': contentType }; var uploader = s3Client.upload(file.path, destPath, headers); uploader.on('error', function(err) { //TODO handle this }); uploader.on('end', function(url) { //TODO do something with the url console.log('file opened:', url); }); }); });}
I changed this from my code, so it may not work out of the box, but hopefully it's helpful!
Recently a new package was added to the list of packages on mean.io. It's a beauty!
Simply run:
$ mean install mean-upload
This installs the package into the node folder but you have access to the directives in your packages.
http://mean.io/#!/packages/53ccd40e56eac633a3eee335
On your form view, add something like this:
<div class="form-group"> <label class="control-label">Images</label> <mean-upload file-dest="'/packages/photos/'" upload-file-callback="uploadFileArticleCallback(file)"></mean-upload> <br> <ul class="list-group"> <li ng-repeat="image in article.images" class="list-group-item"> {{image.name}} <span class="glyphicon glyphicon-remove-circle pull-right" ng-click="deletePhoto(image)"></span> </li> </ul> </div>
And in your controller:
$scope.uploadFileArticleCallback = function(file) { if (file.type.indexOf('image') !== -1){ $scope.article.images.push({ 'size': file.size, 'type': file.type, 'name': file.name, 'src': file.src }); } else{ $scope.article.files.push({ 'size': file.size, 'type': file.type, 'name': file.name, 'src': file.src }); } }; $scope.deletePhoto = function(photo) { var index = $scope.article.images.indexOf(photo); $scope.article.images.splice(index, 1); }
Enjoy!
Mean-upload has been obsoleted and is now called "upload". It is managed in - https://git.mean.io/orit/upload