如何用express 和 request 转发带文件请求
发布于 8 年前 作者 LiuWenLibra 16024 次浏览 来自 问答

场景是express接收到req中的文件后需要将文件转发至远端接口

var
 express = require('express'),
request = require('request'),
multer  = require('multer'),
upload = multer({ dest: 'uploads/' }),
Q = require('q'),
app=express();
app.post('/sapi/servlet/fileupload', upload.single('file'), function (req, res, next) {
    console.log(req.file);
        var reqParam = {
            method:req.method,
            url: 'http://xxx.xxx.xxx/upload',
            qs: req.query,
            body: req.body,
            headers: {
                
            },
            json: true
        };
		var deferred = Q.defer();
    request(reqParam, function (err, res, body) {
        if (err) {
            return deferred.reject(new ServiceReqError('ServiceRequestError', 500, err));
        }
        if(res){
            if (res.statusCode && (res.statusCode !== 200 || !body)) {
                return deferred.reject(new ServiceReqError('ServiceRequestError', res.statusCode, body || 'error'));
            }
        }
        if(body){
            //if (body.statusCode && (body.statusCode !== '200' || body.result !== 'true')){
            //    return deferred.reject(new ServiceReqError('ServiceRequestError', body.message || '服务器离家出走'));
            //}
        }
        //console.log(res.headers);
        deferred.resolve([body,res]);
    });

    return deferred.promise;
        
  });
7 回复

request是个牛b的模块,我觉得最容易想到的办法就是构造request的form,转发之。能利用stream最好了

@DevinXian stream如何将req.file转为流传入reqParam 中?

@LiuWenLibra req.file不是blob一类的,要读取上传的文件吧

@DevinXian 我这样写为什么远端还是接不到文件?

app.post('/upload', upload.single('file'), function (req, res, next) {
    console.log(req.file);
    var fs = require('fs');
    var http = require('http');

    var boundaryKey = '----' + new Date().getTime();
        var options = {

        host:'xxx.xxx.xxx',//远端服务器域名

        port:80,//远端服务器端口号

        method:req.method,

        path:'/fileupload',//上传服务路径

        headers:{

        'Content-Type':'multipart/form-data; boundary=' + boundaryKey,

        'Connection':'keep-alive'

        },

    };
        var request = http.request(options,function(res){

            res.setEncoding('utf8');

            res.on('data', function (chunk) {

                console.log('body: ' + chunk);

            });

            res.on('end',function(){

                console.log('res end.');

            });

        });

        request.write(

        '–' + boundaryKey + '\r\n' +

        'Content-Disposition: form-data; name='+req.file.fieldname+'; filename='+req.file.originalname+'\r\n' +

        'Content-Type: '+req.file.mimetype+'\r\n\r\n'

    );


        var fileStream = fs.createReadStream(req.file.path,{bufferSize:1024 * 1024 * 200});

        fileStream.pipe(request,{end:false});

        fileStream.on('end',function(){

          request.end('\r\n–' + boundaryKey + '–');

        });

  });

不要使用 multer 接收, 直接 Pipe 即可

app.post('upload', function(req, res){
  var type = req.get('content-type');
  var localReq = request({ /* 后端 */ }); // 记得设置 content-type 以保留 boundary
  req.pipe(localReq);
  localReq.pipe(res);
});

request 可能是这样 pipe 的. superagent 是这样的

request = require 'superagent'
localReq = request
  .post url
  .type req.get('content-type')

req.pipe localReq
localReq.pipe res
回到顶部