Загрузка файла из формы на сервер

В настоящее время я работаю над приборной панелью и застрял на несколько часов… Что мне нравится делать, так это иметь форму, включающую 3 <input type="file">(два из них разрешают несколько файлов, один нет), и каждый из них публикует 3 различных метода post на сервере. Когда я пытаюсь консольно регистрировать запрос на стороне сервера, данные пусты ({}). Я не понимаю, почему, может кто-то, пожалуйста, помочь мне решить эту проблему?

Я использую 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
            });
        };
 }

Сервер.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, я изменил сервер.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 ответа

  1. При загрузке файла форма должна использовать multipart / form-data, которые body-parser не поддерживает. Для обработки этого типа необходимо использовать специализированное промежуточное ПО. Мультер-один из таких, которым я пользовался с успехом.

  2. Вы можете обойти это с помощью FileReader.readAsDataURL(..) о файловых объектах в полях ввода. Я часто использую возможность множественного выбора на типе ввода файла, чтобы я мог загрузить кучу файлов и сделать это асинхронно.

    Таким образом, что я обычно делаю, это доступ к свойству files на входном элементе и цикл через них, то я использую FileReader.readAsDataURL, чтобы получить base64 двоичного файла для файлов, а затем передать base64 в метод webserivce с подписью, которая принимает, что строка param для 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>

    Я не включил серверный компонент к этому, потому что я думаю, что это должно быть agnostic и немного из области здесь.

    Я только регистрирую выход в консоль, но вы бы взяли выход и перекачали его в веб-службу.

    Кроме того, я сослался на элемент input в обработчике событий для onchange, используя «это», потому что я понятия не имел, как вы хотите обработать его. Разрешение на прохождение элемента обеспечило немного расплывчатых предположений с моей стороны.