从Node Express将内存中的文件发送到API

3

我有一个在Node和Express中的API,它接收来自客户端(Postman开发版)的文件,我使用multer将文件存储在内存中,代码如下:

router.post('/api/v1/upload', contrl.upload, contrl.uploadFile);

然后在我的控制器中:

exports upload = multer({ storage: multer.memoryStorage() }).single('file');

现在我可以通过req.file.buffer访问文件,但是我想将这个文件发送到另一个API。 我正在使用request-promise-native,所以代码应该类似于:

const rp = require('request-promise-native')

exports.uploadFile = (req, res) => {

  const options = {
    method: 'POST',
    uri: `${uri}`,
    form: {
      file: req.file.buffer
    }
  }

  rp(options)
    .then(parsedBody => {
      return res.status(201).send(parsedBody);
    })
    .catch(err => res.status(400).send(err));
}

为了简化,我删除了其他参数,但这并不起作用,可能是因为Node不知道如何处理req.file.buffer中的信息。

编辑. 经过一些测试后,我尝试使用真实文件而不是使用multer memoryStorage来使其工作。所以我得到了这个:

exports upload = multer({ dest: 'uploads/' }).single('file');

将文件保存到磁盘中,然后

const request = require('request')

exports.uploadFile = (req, res) => {

  const formData = {
    file: fs.createReadStream('uploads/' + req.file.filename)
  }
  const options = {
    url: `${uri}`
    formData
  }

  request.post(options, (err, response, body) => {
    if (err) return res.status(400).send(err);
    return res.status(201).send(response);
  });
}

它是有效的! 但当我在multer中切换到memoryStorage,并使用file:req.file.buffer时,它不起作用。

编辑2: 当我尝试将文件作为流发送时,也尝试了这个方法。

const bufferStream = new stream.PassThrough();
bufferStream.end(req.file.buffer);

我想知道如何实现将bufferStream作为formData传递,因为目前这样做并不起作用。

谢谢

5个回答

3

我曾多次遇到同样的问题,但总是得到不好的解决方案。感谢此帖中的所有人。 以下是我使用aixios的解决方案,以防有人需要。

//First use form-data
const FormData = require('form-data') ;
//use axios
const axios = require('axios') ;


//Note is very important passing contentType and filename 
//options
let form = new FormData() ;
//consider req.file is the file coming from multer
form.append('file',req.file.buffer,{
     contentType:req.file.mimetype,
     filename:req.file.originalname
  }) ;


//now do a post request with axios
// personally I like the use of async-await for promises but
//then() catch() will work just fine
let response = await axios.post('API_URL', form, {
  headers: form.getHeaders() 
});
// whatever you need with response ex.
console.log(response.data)

2

最近我遇到了类似的情况,我的解决过程是:从web到node再到PHP。我使用了"multer"和"request"来解决这个问题,而且没有使用真实文件。

    const multer  = require('multer')
    const upload = multer();
    const request = require('request');

    router.post('/upload', upload.single('img'),(req,res,next) => {

        let formData = {
            'quality':80,
            //file field need set options 'contentType' and 'filename' for formData
            'file':{
                value:req.file.buffer,
                options:{
                    contentType:req.file.mimetype,
                    filename:req.file.originalname
                }
            }
        }    
       request.post({
             url:''/**uploadurl*/,
             formData
       },function(err,response,body){res.send(body)})
    })

0

这应该可以解决你的问题

const http = require('http');
exports.uploadFile = (req, res) => {
    // create new request to reupload file
    const request = http.request({  
        port : 80,
        hostname : '127.0.0.1',
        method : 'POST',
        path : '/'
    });
    let result = '';
    // grab response from new request
    request.on('data', (chunk) => {
        result += chunk;
    });
    // resend response from new request
    request.on('end', () => {
        res.status(201).end(result);
    });
    // resend error from new request
    request.on('error', (err) => {
        res.status(400).end(err);
    });
    // pipe your file to new request
    req.file.stream.pipe(request);
};

0
使用Node内存流https://www.npmjs.com/package/memory-streams
var streams = require('memory-streams')
  , fs      = require('fs');

// Pipe  
var reader = fs.createReadStream('index.js');
var writer = new streams.WritableStream();
reader.pipe(writer);
reader.on('readable', function() {

  // Output the content as a string 
  console.log(writer.toString());

  // Output the content as a Buffer 
  console.log(writer.toBuffer());
});

0
const rp = require('request-promise-native')

exports.uploadFile = (req, res) => {

  const options = {
    method: 'POST',
    uri: `${uri}`,
    formData: {
      file: req.file.buffer
    }
  }

  rp(options)
    .then(parsedBody => {
      return res.status(201).send(parsedBody);
    })
    .catch(err => res.status(400).send(err));
}

我遇到了一个错误。我需要一些特殊的头文件或其他东西吗?在响应中,我可以看到"error": "Bad Request", "options": { "method":"POST", "uri": "....", "file": "cHJ1ZWJh=="} - David
请检查您正在调用的API。它们可能期望请求以某种特定方式完成。 - Julien Klepatch
没什么特别的。如果我使用Postman并发送一个带有表单数据和文件作为File的POST请求,API就可以正常工作。当我检查请求有效载荷时,我会得到文件的Content-Type:text/plain,但是如果我使用上述机制,它将成为二进制对象,所以我猜测某些地方不太对,API不知道如何解释这个。 - David
当您使用base64编码时,您发送的是明文而不是二进制数据。如果您不使用base64编码会发生什么? - Julien Klepatch
如果我不使用base64,那么在请求头中我会看到以下内容: "form": { ... "file": { "type": "Buffer", "data": [ 112, 114, 117, 101,... ]}}",并且API会返回相同的错误。 - David
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接