jtlindsey
jtlindsey

Reputation: 4863

Upload file to another server with request or axios nodejs

I have a user form where a user can pick a file on their system and upload it to another server using the FormData. It works fine when testing sending it directly to the api. But I need to modify the headers before sending it. So I'm posting to the backend of the client app.

router.post('/upload', function(req, res, next) {
  //...some axios or request logic

  var fs = require('fs');
  var request = require('request');
  var formData = {
    my_field: 'my_value',
    my_file: fs.createReadStream(__dirname + '/example.doc'),
  };

  request.post({url:'http://someothereapp/upload-file', formData: formData}, function(err, httpResponse, body) {
    if (err) {
      return console.error('upload failed:', err);
    }
    console.log('Upload successful!  Server responded with:', body);
    res.send('good!');
  });

});

axios or request works great for posting normal forms or get request. But when I try to use it to send a file it doesn't work. The above code always returns success but does not upload the file. So i went here and still don't understand enough to see what I am missing.

I have authentication and tracking turned off on the other server (local) while testing so i don't have to modify headers. It has the following code that works fine if I send the file directly to it from the web form, but not from my client express app:

  // http://someothereapp/upload-file
  router.post('/upload-file', (req, res, next) => {
    let multer = require('multer')
    let p =  path.join(__dirname, '../uploads');
    let storage = multer.diskStorage({
      destination: function(req, file, callback) {
        callback(null, p )
      },
      filename: function(req, file, callback) {
        console.log('what is file', file)
        callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
      }
    })

    let upload = multer({
      storage: storage
    }).single('userFile')
    upload(req, res, function(err) {
      res.end('File is uploaded')
    })
  });

I saw this issue and think it might mean its not possible with axios but how do you do it with request? For example, in the post ... upload code, how do i get my_file to be the file the user selected in their form? Why is it not failing even though it's not uploading a file?

Upvotes: 2

Views: 2151

Answers (1)

jtlindsey
jtlindsey

Reputation: 4863

I changed the client backend app to the following and it allows me to modify headers and send the form:

router.post('/upload-file', function(req, res, next) {
  var httpProxy = require('http-proxy');
  var proxy = httpProxy.createProxyServer({headers: customHeader});
  proxy.web(req, res, { target: 'http://someothereapp' }, function(e) { 
    // will proxy request to http://someothereapp/upload-file
    ...
  });
});

The client form (unchanged):

<form name='uploadfile'  enctype="multipart/form-data" method="post">
  <input type="file" name="userFile" />
  <input type="submit" value="Upload File" name="submit">
</form>


<script>
var form = document.forms.namedItem("uploadfile");
form.addEventListener('submit', function(ev) {

  var oOutput = document.querySelector("div"),
      oData = new FormData(form);

  var oReq = new XMLHttpRequest();
  oReq.open("POST", "/upload-file", true);
  oReq.onload = function(oEvent) {
    if (oReq.status == 200) {
      // oOutput.innerHTML = "Uploaded!";
      console.log('Uploaded');
    } else {
      console.log('error', oReq.status);
      // oOutput.innerHTML = "Error " + oReq.status + " occurred when trying to upload your file.<br \/>";
    }
  };

  oReq.send(oData);
  ev.preventDefault();
}, false);
</script>

The target server (unchanged):

  // http://someothereapp/upload-file
  router.post('/upload-file', (req, res, next) => {
    let multer = require('multer')
    let p =  path.join(__dirname, '../uploads');
    let storage = multer.diskStorage({
      destination: function(req, file, callback) {
        callback(null, p )
      },
      filename: function(req, file, callback) {
        console.log('what is file', file)
        callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
      }
    })

    let upload = multer({
      storage: storage
    }).single('userFile')
    upload(req, res, function(err) {
      res.end('File is uploaded')
    })
  });

Upvotes: 1

Related Questions