MEAN Stack File uploads

后端 未结 4 1528
生来不讨喜
生来不讨喜 2021-01-30 15:08

I\'ve recently started programming with the MEAN Stack, and I\'m currently implementing some sort of social network. Been using the MEAN.io framework to do so. My main problem r

相关标签:
4条回答
  • 2021-01-30 15:26

    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!

    0 讨论(0)
  • 2021-01-30 15:31

    I know this post is old. I came across it and @kentcdodds had an answer that i really liked, but the libraries he used are now out of date and I could not get them to work. So after some research i have a newer similar solution I want to share.

    HTML using ng-upload

    <form >
        <div style="margin-bottom: 15px;">
            <button type="file" name="file" id="file" ngf-select="uploadFiles($file, $invalidFiles)" accept="image/*" ngf-max-height="1000" ngf-max-size="1MB">Select File</button>
        </div>
    </form>
    

    INCLUDE ng-upload module

    download it, references the files and include the module

    var app = angular.module('app', ['ngFileUpload']);
    

    this will give you access to the Upload service.

    Controller code

    $scope.uploadFiles = function(file, errFiles) {
        $scope.f = file;
        $scope.errFile = errFiles && errFiles[0];
        if (file) {
            file.upload = Upload.upload({
                url: 'you-api-endpoint',
                data: {file: file}
            });
    
            //put promise and event watchers here if wanted
        }   
    };
    

    NODE api code

    All the code below is in a separate route file which is required in my main server.js file.

    require('./app/app-routes.js')(app, _);

    var fs = require('fs');
    var uuid = require('uuid');
    var s3 = require('s3fs'); // https://github.com/RiptideElements/s3fs
    var s3Impl = new s3('bucketname', {
        accessKeyId: '<your access key id>',
        secretAccessKey: '< your secret access key >'
    });
    
    var multiparty = require('connect-multiparty');
    var multipartyMiddleware = multiparty();
    
    module.exports = function(app, _) {
        app.use(multipartyMiddleware);
    
    
        app.post('/your-api-endpoint',function(req, res){
    
        var file = req.files.file; // multiparty is what allows the file to to be accessed in the req
        var stream = fs.createReadStream(file.path);
        var extension = file.path.substring(file.path.lastIndexOf('.'));
        var destPath = '/' + req.user._id + '/avatar/' +  uuid.v4() + extension;
        var base = 'https://you-bucket-url';
        return s3Impl.writeFile(destPath, stream, {ContentType: file.type}).then(function(one){
            fs.unlink(file.path);
            res.send(base + destPath); 
        });
    });
    

    All i was trying to do was upload a unique avatar for a user. Hope this helps!!

    0 讨论(0)
  • 2021-01-30 15:34

    Mean-upload has been obsoleted and is now called "upload". It is managed in - https://git.mean.io/orit/upload

    0 讨论(0)
  • 2021-01-30 15:37

    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-uuid
    var multiparty = require('multiparty'); // https://github.com/andrewrk/node-multiparty
    var s3 = require('s3'); // https://github.com/andrewrk/node-s3-client
    
    var 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!

    0 讨论(0)
提交回复
热议问题