Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/473.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 管道多部分表单上载到另一台服务器_Javascript_Angularjs_Node.js_Express_Multipartform Data - Fatal编程技术网

Javascript 管道多部分表单上载到另一台服务器

Javascript 管道多部分表单上载到另一台服务器,javascript,angularjs,node.js,express,multipartform-data,Javascript,Angularjs,Node.js,Express,Multipartform Data,我试图在我的Node Express服务器上处理POST请求,以处理多部分表单上载,在我的情况下,用户正在上载图像 我想通过我的Express应用程序将上传到另一台服务器,该应用程序当前设置为使用body parser,我还看到它不支持多部分bodes,而是建议使用其他一些库 我已经看过了,但我不确定如何在客户端应用程序中使用它 在我的客户端代码中,我发布了一个FormData对象,如下所示: function create(data, name) { var formData = new

我试图在我的Node Express服务器上处理POST请求,以处理多部分表单上载,在我的情况下,用户正在上载图像

我想通过我的Express应用程序将上传到另一台服务器,该应用程序当前设置为使用body parser,我还看到它不支持多部分bodes,而是建议使用其他一些库

我已经看过了,但我不确定如何在客户端应用程序中使用它

在我的客户端代码中,我发布了一个FormData对象,如下所示:

function create(data, name) {
  var formData = new FormData();
  formData.append('file', data, name);
  return this.parentBase.one('photos').withHttpConfig({transformRequest: angular.identity}).customPOST(formData, undefined, undefined, {'Content-Type': undefined});
}
注意:我正在使用AngularJS的Restangular库,如文档所示

因此,从我对多方文档的理解来看,我必须处理表单上传事件,并在表单上传完成后采取进一步行动

问题是,我希望我可以直接通过管道上传到另一台服务器。之前,我的客户端应用程序直接呼叫另一台服务器,但我现在尝试通过Express将所有内容路由,这是可能的,还是我必须使用类似多方的东西

请求文档给出了一个使用的示例,但我不确定这将如何与我所看到的多方示例配合使用。例如,使用mutliparty在Express中完成上载后,我是否必须构造另一个formData对象,然后与该对象进行进一步请求,还是必须将每个部分通过管道传输到其他服务器

我很困惑,有人能帮我澄清一下吗

谢谢

编辑

好的,我已经看了multer下面的@yarons评论,这似乎是我想要使用的东西,我已经尝试在我的express router设置中使用它,如下所示:

routes.js

var express = require('express'),
  router = express.Router(),
  customers = require('./customers.controller.js'),
  multer = require('multer'),
  upload = multer();

router.post('/customers/:customerId/photos/', upload.single('file'), customers.createPhoto);
module.exports.createPhoto = function(req, res) {
  console.log(req.file);
  var options = prepareCustomersAPIHeaders(req);
  options.formData = req.file;
  request(options).pipe(res);
};
controller.js

var express = require('express'),
  router = express.Router(),
  customers = require('./customers.controller.js'),
  multer = require('multer'),
  upload = multer();

router.post('/customers/:customerId/photos/', upload.single('file'), customers.createPhoto);
module.exports.createPhoto = function(req, res) {
  console.log(req.file);
  var options = prepareCustomersAPIHeaders(req);
  options.formData = req.file;
  request(options).pipe(res);
};
在上述控制器中注销req.file属性时,我看到:

{ fieldname: 'file',
  originalname: '4da2e703044932e33b8ceec711c35582.jpg',
  encoding: '7bit',
  mimetype: 'image/png',
  buffer: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 fa 00
 00 00 fa 08 06 00 00 00 88 ec 5a 3d 00 00 20 00 49 44 41 54 78 5e ac bd f9 8f e
6 e9 7a ... >,
  size: 105868 }
我所尝试的是否明智?只是它不起作用,我从我试图发布的服务器返回了一个错误。在此之前,我直接向服务器发出此post请求时,一切正常,因此我的Express\Multer设置中一定出了问题

编辑2

好的,在进行了更多的搜索之后,我看到了一篇使用multiparty的文章,我让manager在我的设置中工作,如下所示:

var request = require('request'),
  multiparty = require('multiparty'),
  FormData = require('form-data');

module.exports.createPhoto = function(req, res) {
  //console.log(req.file);
  var options = prepareCustomersAPIHeaders(req),
    form = new multiparty.Form();
  options.headers['Transfer-Encoding'] = 'chunked';

  form.on('part', function(part){
    if(part.filename) {
      var form = new FormData(), r;
      form.append(part.name, part, {filename: part.filename, contentType: part['content-type']});


      r = request(options, function(err, response, body){
        res.status(response.statusCode).send(body);
      });
      r._form = form
    }
  });

  form.on('error', function(error){
    console.log(error);
  });

  form.parse(req);
};  
现在,我正在按预期将文件上载到我的其他服务器上,虽然此解决方案可行,但我不喜欢以下行:

r._form = form
似乎正在为请求对象分配一个私有表单变量,而且我在多方页面上看不到任何以这种方式记录的内容


有人能对这一可能的解决方案提出任何意见吗?

我们使用以下方法:

客户

//HTML
    <input type="file" ng-file-select uploader="info.uploadPath" />


//DIRECTIVES
  // It is attached to <input type="file" /> element
  .directive('ngFileSelect', function() {
    return {
      link: function($scope, $element) {
        $element.bind('change', function() {
          $scope.$emit('file:add', this.files ? this.files : this);
        });
      }
    };
  })

//OTHER
    var uploadPath = '/api/things/' + $stateParams.thingId + '/add_photo'

    var uploadInfo = {
              headers: {
                'Authorization': authToken
              },
              form: {
                title: scope.info.name
              }
            }


//SERVICE:
  $rootScope.$on('file:add', function(event, items) {
    this.addToQueue(items);
  }.bind(this));
  ...
  addToQueue: function(items) {
    var length = this.queue.length;
    angular.forEach(items.length ? items : [items], function(item) {
      var isValid = !this.filters.length ? true : !!this.filters.filter(function(filter) {
        return filter.apply(this, [item]);
      }, this).length;

      if (isValid) {
        item = new Item({
          url: this.url,
          alias: this.alias,
          removeAfterUpload: this.removeAfterUpload,
          uploader: this,
          file: item
        });

        this.queue.push(item);
      }
    }, this);

    this.uploadAll();
  },
  getNotUploadedItems: function() {
    return this.queue.filter(function(item) {
      return !item.isUploaded;
    });
  },

  /**
   * Upload a item from the queue
   * @param {Item|Number} value
   */
  uploadItem: function(value, uploadInfo) {
    if (this.isUploading) {
      return;
    }

    var index = angular.isObject(value) ? this.getIndexOfItem(value) : value;
    var item = this.queue[index];
    var transport = item.file._form ? '_iframeTransport' : '_xhrTransport';
    this.isUploading = true;
    this[transport](item, uploadInfo);
  },

  uploadAll: function(uploadInfo) {
    var item = this.getNotUploadedItems()[0];
    this._uploadNext = !!item;
    this._uploadNext && this.uploadItem(item, uploadInfo);
  },

  _xhrTransport: function(item, uploadInfo) {
    var xhr = new XMLHttpRequest();
    var form = new FormData();
    var that = this;

    form.append(item.alias, item.file);

    angular.forEach(uploadInfo.form, function(value, name) {
      form.append(name, value);
    });

    xhr.upload.addEventListener('progress', function(event) {
      var progress = event.lengthComputable ? event.loaded * 100 / event.total : 0;
      that._scope.$emit('in:progress', item, Math.round(progress));
    }, false);

    xhr.addEventListener('load', function() {
      xhr.status === 200 && that._scope.$emit('in:success', xhr, item);
      xhr.status !== 200 && that._scope.$emit('in:error', xhr, item);
      that._scope.$emit('in:complete', xhr, item);
    }, false);

    xhr.addEventListener('error', function() {
      that._scope.$emit('in:error', xhr, item);
      that._scope.$emit('in:complete', xhr, item);
    }, false);

    xhr.addEventListener('abort', function() {
      that._scope.$emit('in:complete', xhr, item);
    }, false);

    this._scope.$emit('beforeupload', item);

    xhr.open('POST', item.url, true);

    angular.forEach(uploadInfo.headers, function(value, name) {
      xhr.setRequestHeader(name, value);
    });

    xhr.send(form);
  },

你试过了吗?这是一个中间件,可以让你在上传文件后访问它,你不需要听upload EventsHanks@yarons,这似乎是一个更简单的库,我用我尝试过的代码编辑了我的文章,但我还不能让它工作。我正在客户机中构造一个formData对象,用于最初的post表达,因此我希望在我要对另一台服务器进行的请求调用中使用它作为formData参数值。现在我似乎不得不使用两个formData对象,这两个对象闻起来不太对劲。对不起,我只是在向你扔第三方软件包……谢谢@yarons的建议,我不太确定我是否还想看另一个软件包。我会继续挖掘,希望有人能提供一些其他想法。