Q:

NodeJS: How to Send a file via Request POST

I am using REQUEST (https://www.npmjs.org/package/request) to send a file via filepicker and I can't seem to figure out how. I did this back in ruby via RestClient, and it looks like this:
response = RestClient.post "https://www.filepicker.io/api/store/S3?key=#{@api_key}",
  { fileUpload: File.new(zip_path), mimetype: 'application/zip',
    filename: "filename.zip", multipart:true, access: 'public'}

I have two questions for this, (1) what is the counterpart of the parameters in REQUEST (is it form? body? header?)? and (2) how do we access the file in the node filesystem such that it can be sent in the request (i.e. counterpart of File.new)?

A:

I had a fair bit of trouble sorting this out as well. Perhaps I missed something, but it seemed unusually complicated to get working. It involved using the form-data module directly (which, interestingly, request does depend on). 
At the root of the problem was a race condition with ensuring that the form containing all of the file data was available to the request for the upload before the call was made. I finally followed the advice one user offered in the issue comments; I created the form first (rather than using the version created automatically by the request module), then updated the request object to use that form instead:
Here's a slimmed-down version of the solution I finally went with:
var FormData = require('form-data');
var request = require('request');

function upload(filepath, url, cb) { //cb(error)

    // Create the form with your file's data appended FIRST
    var form = new FormData();
    form.append('file', fs.createReadStream(filepath));

    // Needed to set the Content-Length header value
    form.getLength(function(err,length) {

        var opts = {
            headers: {
                'Content-Length': length
            }
        };

        // Create the request object
        var r = request.post(url, opts, function(error, res, body) {

            /*

             Do things...

             */

            cb(error);
        });

        // Explicitly set the request's form property to
        // the form you've just created (not officially supported)
        r._form = form;
    });
}

