无法将文件从Angularjs上传到Expressjs

时间:2014-05-12 10:10:33

标签: node.js angularjs mean-stack mean.io

我试图将图像从AngularJS界面上传到nodejs服务器(expressjs)。 (我使用mean.io

每次上传某些内容时,req.body记录" {}"和req.files日志" undefined"

我在AngularJS中使用angular-file-upload指令

客户端代码:

$scope.onFileSelect = function() {
    console.log($files);
    for (var i = 0; i < $files.length; i++) {
      var file = $files[i];
      $scope.upload = $upload.upload({
        url: 'map/set', 
        method: 'POST',
        headers: {'enctype': 'multipart/form-data'},
        data: {myObj: $scope.myModelObj},
        file: file,

      }).progress(function(evt) {
        console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
      }).success(function(data, status, headers, config) {
        // file is uploaded successfully
        console.log(data);
      });
    }
  };

服务器端代码

var app = express();
require(appPath + '/server/config/express')(app, passport, db);
app.use(bodyParser({uploadDir:'./uploads'}));
app.post('/map/set', function(req, res) {
    console.log(req.body);
        console.log(req.files);
    res.end('Success'); 
});

*****编辑*****

HTML代码

<div class="row">
    <input id="file" type="file" ng-file-select="onFileSelect()" >
</div>

手工构建的请求

$scope.onFileSelect = function() {
    //$files: an array of files selected, each file has name, size, and type.
    //console.log($files);

    var xhr = new XMLHttpRequest();
    // not yet supported in most browsers, some examples use
    // this but it's not safe.
    // var fd = document.getElementById('upload').getFormData();

    var fd = new FormData();
    var files = document.getElementById('myfileinput').files;
    console.log(files);
    for(var i = 0;i<files.length; i++) {
        fd.append("file", files[i]);
    }

    /* event listeners */
    xhr.upload.addEventListener("progress", uploadProgress, false);
    xhr.addEventListener("error", uploadFailed, false);
    xhr.addEventListener("load", uploadComplete, false);
    xhr.addEventListener("abort", uploadCanceled, false);

    function uploadComplete(){
        console.log("complete");
    }

    function uploadProgress(){
        console.log("progress");
    }

    function uploadFailed(){
        console.log("failed");
    }

    function uploadCanceled(){
        console.log("canceled");
    }

    xhr.open("POST", "map/set");

    xhr.send(fd);


  };

3 个答案:

答案 0 :(得分:2)

我将在这里猜测标题设置不正确。

   headers: {'enctype': 'multipart/form-data'},

应改为:

   headers: {'Content-Type': 'multipart/form-data'},

答案 1 :(得分:2)

最新版本的mean.io不包括表达4.x作为依赖。在迁移快递3到4的文档中你可以阅读,表示将不再使用连接中间件。阅读更多相关信息:https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x 新的body-parser模块只处理urlencoded和json主体。这意味着对于多部分机构(文件上传),您需要一个额外的模块,如busboyformadible。 以下是我如何使用带有busboy的angular-file-upload的示例: AngularJS Stuff:

$upload.upload({
  url: '/api/office/imageUpload',
  data: {},
  file: $scope.$files
}) …

我写了一个小助手模块,以便更轻松地处理上传。这不是很干净的编码,但做的工作:

var env = process.env.NODE_ENV || 'development';
var Busboy = require('busboy'),
    os = require('os'),
    path = require('path'),
    config = require('../config/config')[env],
    fs = require('fs');

// TODO: implement file size limit

exports.processFileUpload = function(req, allowedExtensions, callback){
  var busboy = new Busboy({ headers: req.headers });
  var tempFile = '';
  var fileExtenstion = '';
  var formPayload = {};

  busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
    fileExtenstion = path.extname(filename).toLowerCase();
    tempFile = path.join(os.tmpDir(), path.basename(fieldname)+fileExtenstion);
    file.pipe(fs.createWriteStream(tempFile));
  });

  busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
    var jsonValue = '';

    try {
      jsonValue = JSON.parse(val);
    } catch (e) {
      jsonValue = val;
    }

    formPayload[fieldname] = jsonValue;
  });

  busboy.on('finish', function() {
    if(allowedExtensions.length > 0){
      if(allowedExtensions.indexOf(fileExtenstion) == -1) {
        callback({message: 'extension_not_allowed'}, tempFile, formPayload);
      } else {
        callback(null, tempFile, formPayload)
      }
    } else {
      callback(null, tempFile, formPayload)
    }
  });

  return req.pipe(busboy);
}

在我的控制器中,我可以使用模块:

var uploader = require('../helper/uploader'),
    path = require('path');


exports.uploadEmployeeImage = function(req,res){    
    uploader.processFileUpload(req, ['.jpg', '.jpeg', '.png'], function(uploadError, tempPath, formPayload){

    var fileExtenstion = path.extname(tempPath).toLowerCase();
    var targetPath = "/exampleUploadDir/testFile" + fileExtenstion;

    fs.rename(tempPath, targetPath, function(error) {
      if(error){
        return callback("cant upload employee image");
      }

      callback(null, newFileName);
    });
  });
}

答案 2 :(得分:1)

确保您拥有&#39; id&#39; AND&#39; name&#39; file input上的属性 - 没有id属性可能会导致某些浏览器出现问题。另外,尝试构建这样的请求:

    var xhr = new XMLHttpRequest();
    // not yet supported in most browsers, some examples use
    // this but it's not safe.
    // var fd = document.getElementById('upload').getFormData();

    var fd = new FormData();
    var files = document.getElementById('myfileinput').files;
    for(var i = 0;i<files.length; i++) {
        fd.append("file", files[i]);
    }

    /* event listeners */
    xhr.upload.addEventListener("progress", uploadProgress, false);
    xhr.addEventListener("error", uploadFailed, false);
    xhr.addEventListener("load", uploadComplete, false);
    xhr.addEventListener("abort", uploadCanceled, false);
    xhr.open("POST", "your/url");

    xhr.send(fd);

对于文件上传来说,角度并不是很好,所以手动操作可能会有所帮助。