19

我最近开始使用 MEAN Stack 进行编程,目前正在实施某种社交网络。一直在使用 MEAN.io 框架来做到这一点。我现在的主要问题是让文件上传工作,因为我想要做的是从表单接收文件到 AngularJS 控制器并将它与更多信息一起传递给 ExpressJS,这样我最终可以将所有内容发送到 MongoDB。(我正在构建一个注册新用户表单)。

我不想将文件本身存储在数据库中,但我想存储指向它的链接。

我用不同的搜索查询在谷歌上搜索了几十个页面,但我找不到任何我能理解或工作的东西。一直在寻找几个小时没有结果。这就是我来这里的原因。

谁能帮我这个?

谢谢 :)

编辑:也许一些代码将有助于理解。

我用作基础的默认 MEAN.io 用户 Angular 控制器具有以下功能:

$scope.register = function(){
        $scope.usernameError = null;
        $scope.registerError = null;
        $http.post('/register', {
            email: $scope.user.email,
            password: $scope.user.password,
            confirmPassword: $scope.user.confirmPassword,
            username: $scope.user.username,
            name: $scope.user.fullname
        })//... has a bit more code but I cut it because the post is the main thing here.
    };

我想要做的是:从表单接收一个文件,到这个控制器上,并将它与电子邮件、密码、姓名等一起传递,并能够在位于服务器端的 expressjs 上使用 json。'/register' 是一个 nodejs 路由,因此是一个服务器控制器,它创建用户(使用用户模式)并将其发送到 MongoDB。

4

4 回答 4

27

我最近做了这样的事情。我使用了 angular-file-upload。您还需要node-multiparty为您的端点解析表单数据。然后您可以使用s3将文件上传到 s3。

这是我的一些[编辑]代码。

角模板

<button>
  Upload <input type="file" ng-file-select="onFileSelect($files)">
</button>

角度控制器

$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);
  });
};

路线

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);
      });
    });
  });
}

我从我的代码中更改了它,所以它可能无法开箱即用,但希望它会有所帮助!

于 2014-04-14T17:13:07.813 回答
3

最近,mean.io 上的软件包列表中添加了一个新软件包。这是一个美女!

只需运行:

$ 意思是安装意思是上传

这会将包安装到节点文件夹中,但您可以访问包中的指令。

http://mean.io/#!/packages/53ccd40e56eac633a3eee335

在您的表单视图中,添加如下内容:

    <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>

在你的控制器中:

    $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);
    }

享受!

于 2014-08-05T18:45:25.260 回答
0

平均上传已过时,现在称为“上传”。它在 - https://git.mean.io/orit/upload中管理

于 2016-06-21T11:53:32.250 回答
0

我知道这篇文章很旧。我遇到了它,@kentcdodds 有一个我非常喜欢的答案,但是他使用的库现在已经过时了,我无法让它们工作。因此,经过一些研究,我想分享一个更新的类似解决方案。

使用 ng-upload 的 HTML

<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>

包括 ng-upload 模块

下载它,引用文件并包含模块

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

这将使您可以访问该Upload服务。

控制器代码

$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
    }   
};

节点api代码

下面的所有代码都在一个单独的route文件中,该文件required位于我的主 server.js 文件中。

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); 
    });
});

我所要做的就是为用户上传一个独特的头像。希望这可以帮助!!

于 2016-10-18T05:14:03.130 回答