2

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

每次我上传一些东西时,req.body 记录“{}”,req.files 记录“未定义”

我在 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);


  };
4

3 回答 3

2

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

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

我编写了一个小助手模块来更轻松地处理 busboy 的上传。它的编码不是很干净,但可以完成工作:

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);
    });
  });
}
于 2014-05-15T08:33:18.107 回答
2

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

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

应改为:

   headers: {'Content-Type': 'multipart/form-data'},
于 2014-05-12T10:50:13.607 回答
1

确保你有一个 'id' 和 'name' 属性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);

角度不适用于文件上传,因此手动操作可能会有所帮助。

于 2014-05-12T12:01:33.610 回答