将文件从表单上传到服务器

时间:2016-05-01 16:20:51

标签: javascript angularjs node.js http

我目前正在制作一个仪表板,现在已经卡住了几个小时......我喜欢做的是一个包含3 <input type="file">的表单(其中两个允许多个文件,一个不),并且每个人都在服务器中发布了3个不同的post-methods。当我尝试在服务器端控制日志记录时,数据为空({})。我不明白为什么,有人可以帮我解决这个问题吗?

我正在使用angularjs和nodejs btw。

这是我目前的代码:(文件和路径是虚拟名称)

HTML:

 <form role="form" enctype="multipart/form-data">
        <div class="form-group">
            <label for="file1">File1:</label> 
            <input type="file" id="file1" accept=".txt, .json" multiple> 
        </div>
        <div class="form-group">
            <label for="file2">File2:</label> 
            <input type="file" id="file2" accept=".json"> 
        </div>
        <div class="form-group">
            <label for="file3">File3:</label>
            <input type="file" id="file3" multiple> 
        </div>
        <button type="button" ng-click="save()" class="btn btn-default"> Save</button>
    </form>

JS:

module.exports = function($scope, $http) {
        $scope.save = function () {
              file1(document.getElementById('file1').files);
              file2(document.getElementById('file2').files);
              file3(document.getElementById('file3').files);
        };

        function file1(files) { 
            $http.post('/file1', {f: files}).success(function (res) {
               //todo
            });
        };

        function file2(files) { 
            $http.post('/file2', {f: files}).success(function (res) {
              //todo
            });
        };

        function file3(files) { 
            $http.post('/file3', {f: files}).success(function (res) {
              //todo
            });
        };
 }

Server.js

var express = require("express"),
    fs = require("fs"),
    bodyParser = require('body-parser'),

    app.use(express.static("build"));
    app.use(bodyParser());

    app.post('/file1', function (req, res) {
       console.log(req.body.f) // returns empty: {} 
       // like to move files to path: a/b/c
    });

    app.post('/file2', function (req, res) {
       // like to move files to path: a/d/e
    });

    app.post('/file3', function (req, res) {
      // like to move files to path: a/f/g
    });

更新

收到GrimurD的答案后,我修改了server.js,但仍在苦苦挣扎。任何接受者?

var express = require("express"),
        fs = require("fs"),
        bodyParser = require('body-parser'),
        multer = require('multer'), //<-- updated
        upload =  multer({ dest: './uploads/' }) //<-- updated

    app.use(express.static("build"));
    app.use(bodyParser());
    app.use(multer({ dest: './uploads/' }).array()); // <-- updated

    app.post('/file1', upload.array('file1'), function (req, res) {
       console.log(req.body.f) // returns empty: {} 
       console.log(req.files); // returns undefined // <-- updated
       // like to move files to path: a/b/c
    });

    app.post('/file2', upload.single('file2'), function (req, res) {
       console.log(req.file); // returns undefined  // <-- updated
       // like to move files to path: a/d/e
    });

    app.post('/file3', upload.array('file3'), function (req, res) {
      console.log(req.files); // returns undefined // <-- updated
      // like to move files to path: a/f/g
    });

2 个答案:

答案 0 :(得分:0)

上传文件时,表单必须使用body-parser不支持的multipart / form-data。您必须使用专门的中间件来处理此类型。 Multer是我成功使用过的。

答案 1 :(得分:0)

您可以使用输入字段中的File对象上的FileReader.readAsDataURL(..)来解决此问题。我经常喜欢在文件输入类型上使用多选功能,这样我就可以上传一堆文件并执行此异步操作。

所以我通常做的是访问input元素上的files属性并循环遍历它们,然后我使用FileReader.readAsDataURL获取文件的二进制文件的base64,然后将base64传递给webserivce方法一个签名,接受base64的字符串参数,将b64转换为二进制,然后你又回来了。

var fileRunner = {
  files: [],
  run: function(el) {
    this.files = el.files;
    this.read();
  },
  read: function() {

    // begin the read operation
    console.log(this.files.length);
    for (var i = 0; i <= this.files.length - 1; i++) {
      var reader = new FileReader();
      reader.readAsDataURL(this.files[i]);
      reader.onload = this.process
    }

  },
  process: function(evt) {
    var result = evt.target.result
    if (result.length > 0) {
      var parts = result.split(',')
      var dataBsf = parts[parts.length - 1];
      console.log(dataBsf);
      //call method to pass the base 64 here. 
    }
  }
};
<body>
  <input id="fup" type="file" multiple="multiple" onchange="fileRunner.run(this)" />
</body>

我没有在此包含服务器端组件,因为我认为这应该是不可知的并且稍微超出范围。

我只是将输出记录到控制台,但您将获取输出并将其输出到Web服务。

此外,我使用“this”在onchange的事件处理程序中引用了input元素,因为我不知道你想如何处理它。允许传递元素为我提供了一些宽松的假设。