Search code examples
angularjsnode.jsazureexpressnode-request

Post form data using Node/Express and Request module


I am able to download files from a remote vendor API and post these to Azure blob storage per this posting: Download file via Webservice and Push it to Azure Blob Storage via Node/Express

This is working as intended, but now I need to pass form data into the request I make to download the file, as my vendor API will send back different files based on my form data (ex. height and width of the image). This code is what downloads the file into my temporary storage per the URL passed into it via the Request module (https://github.com/request/request):

var r = request(req.body.url).pipe(fs.createWriteStream(tmpFileSavedLocation))

How can I pass in the form data I collect via my HTML form to my node/express call so I can post my form data and get the correct image height and width from my vendors API?

Here is my HTML form:

<form id="newForm" class="form-horizontal" data-ng-submit="createContainer()">
        <div class="form-group">
            <label class="col-lg-2 control-label" for="width">Width *</label>
            <div class="col-lg-2">
                <input class="form-control" name="width" id="width" type="number" step="0.01" max="20" data-ng-model="formInfo.width" required>
            </div>
        </div>
        <div class="form-group">
            <label class="col-lg-2 control-label" for="height">Height *</label>
            <div class="col-lg-2">
                <input class="form-control" name="height" id="height" type="number" step="0.01" max="20" data-ng-model="formInfo.height" required>
            </div>
        </div>
        <div class="col-lg-10 col-lg-offset-2">
            <button type="submit" class="btn btn-primary">Create</button>
        </div>
        <span>{{formInfo}}</span>
    </form>

Here is my Angular Controller:

$scope.createContainer = function () {
        // Create Blob Container
        $http.get('/createcontainer').success(function (data) {
        // This passes back the container name that was created via the createcontainer call                
            var containerName = data;
            var filename1 = 'myfile.png';

            // Unsure of how to pass the formdata in!!!!
            var formData = $scope.formInfo

            // Get myfilepng
            $http.post('/uploadapifiles', { containerName: containerName, filename: filename1, url: 'http://vendorapi.net/ws/getimage' }).success(function (data) {
                console.log(data);
               }, function (err) {
                console.log(err);
            });
        });
    };

Here is the uploadapifiles call in my server.js:

app.post('/uploadapifiles', function (req, res, next) {

var containerName = req.body.containerName;
var filename = req.body.filename;
var tmpBasePath = 'upload/'; //this folder is to save files download from vendor URL, and should be created in the root directory previously.
var tmpFolder = tmpBasePath + containerName + '/';

// Create unique temp directory to store files
mkdirp(tmpFolder, function (err) {
    if (err) console.error(err)
    else console.log('Directory Created')
});

// This is the location of download files, e.g. 'upload/Texture_0.png'
var tmpFileSavedLocation = tmpFolder + filename;

// This syntax will download file from the URL and save in the location asyns
var r = request(req.body.url).pipe(fs.createWriteStream(tmpFileSavedLocation))
r.on('close', function () {
    blobSvc.createBlockBlobFromLocalFile(containerName, filename, tmpFileSavedLocation, function (error, result, response) {
        if (!error) {
            console.log("Uploaded" + result);
            res.send(containerName);
        }
        else {
            console.log(error);
        }
    });
})
});

Solution

  • After clarifying the HTTP method and formats of params which your vendor API required are POST and ['boxHeight','boxWidth'], we only need a little modifications.

    We can post the HTML form data to the node.js backend function which is uploadapifiles, and use the form function of request APIs to post the extra form data to vendor API.

    Here are the modified parts of code snippets:

    Angular controller:

    var formInfo = {boxHeight:$scope.formInfo.height,boxWidth:$scope.formInfo.width};
    $http.post('/uploadapifiles', { containerName: containerName, filename: filename1, formInfo : formInfo ,url: 'http://vendorapi.net/ws/getimage' }).success(function (data){
     ... 
    }
    

    uploadapifiles modification in server: To get post params in node/express, we can leverage bodyParser module,

     //introduce and define middleware
     var bodyParser = require('body-parser');
     app.use(bodyParser.json());
     app.use(bodyParser.urlencoded({ extended: true }));
    
     //in uploadapifiles function 
     var propertiesObject = req.body.formInfo;
     var r = request.post(req.body.url).form(propertiesObject).pipe(fs.createWriteStream(tmpFileSavedLocation
        ));