Send file in memory to API from Node Express

Viewed 7245

I've an API in Node and Express which is receiving a file from a the client (Postman in development) and I use multer to get the file in memory like this:

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

and then in my controller:

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

Now I can access the file with req.file.buffer, but then I want to send this same file to another API. I'm using request-promise-native so this would be something like this:

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));
}

I removed some other params for simplicity, but this is not working, probably because Node doesn´t know how to handle the info inside req.file.buffer.

EDIT. Ok after some tests I tried to make this work with a real file instead of using multer memoryStorage. So I got this:

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

to save the file to disk, and then

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);
  });
}

And it works! But then when I change to memoryStorage in multer and I use file: req.file.buffer instead, it does not work.

EDIT2: I also tried to send the file as a stream when in memory, so I tried this

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

and then passing it in the formData with file: bufferStream but also not working.

How can I achieve this? Thanks

5 Answers

I had the same problem a few times and always end up with a bad solution. thank you all for this post. Here is my solution with aixios in case someone can use it

//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)

I recently encountered a similar situation,My process:web to node to PHP.I use "multer" and "request" resolve this problem and i don't use real file.

    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)})
    })
Related