node.js MEAN 堆栈文件上传

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22941535/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 17:07:20  来源:igfitidea点击:

MEAN Stack File uploads

node.jsangularjsmongodbexpressmean-stack

提问by Cacos

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 right now is getting the file upload to work, because what I want to do is receive the file from the form into the AngularJS Controller and pass it along with more info's to ExpressJS so I can finally send everything to MongoDB. (I'm building a register new user form).

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

I dont want to store the file itself on the database but I want to store a link to it.

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

I've searched dozens of pages on google with different search queries but I couldn't find anything that I could understand or worked. Been searching for hours to no result. That's why I've came here.

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

Can anyone help me with this?

谁能帮我这个?

Thanks :)

谢谢 :)

EDIT: Maybe a bit of the code would help understand.

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

The default MEAN.io Users Angular controller which I'm using as foundation has this:

我用作基础的默认 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.
    };

What I want to do is: Receive a file from a form, onto this controller and pass it along with email, password, name, etc, etc and be able to use the json on expressjs, which sits on the server side. The '/register' is a nodejs route so a server controller which creates the user (with the user schema) and sends it to the MongoDB.

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

回答by kentcdodds

I recently did something just like this. I used angular-file-upload. You'll also want node-multipartyfor your endpoint to parse the form data. Then you could use s3for uploading the file to s3.

我最近做了这样的事情。我使用了angular-file-upload。您还需要节点多方为您的端点解析表单数据。然后您可以使用s3将文件上传到 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!

我从我的代码中更改了它,因此它可能无法立即使用,但希望它会有所帮助!

回答by jmckenney

Recently a new package was added to the list of packages on mean.io. It's a beauty!

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

Simply run:

只需运行:

$ mean install mean-upload

$ 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

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!

享受!

回答by gurpreet-SD

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

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

回答by TravRob

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.

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

HTML using ng-upload

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

INCLUDE ng-upload module

包括 ng-upload 模块

download it, references the files and include the module

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

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

this will give you access to the Uploadservice.

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

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

节点 API 代码

All the code below is in a separate routefile which is requiredin my main server.js file.

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

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

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

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