Kode
Kode

Reputation: 3215

Node/Request Error: "Processing POST Request: No Content-Type"

I have a front end Canvas that I transform into a png file that I need to POST to a third party vendor's api. It passes back to node as a base64 file and I decode it, but when I attempt the upload, it gives me the following error:

Problem processing POST request: no Content-Type specified

However, I am clearly specifying the content type in my POST call. My end goal is to upload the file to my vendor's API.

Here are the key front end aspects:

var canvasImage = document.getElementById("c");
        var img = canvas.toDataURL({
            multiplier: canvasMultiplier
        });

var fileTime = Date.now();
            var myFileName = $scope.productCode + fileTime;
            $scope.filenameForVendor = myFileName;
            var filename = $scope.filenameForVendor;

$http.post('/postVendor', { filename: filename, file: img }).success(function (data) {
                console.log("Uploaded to Vendor");

Here is the backend POST:

app.post('/postVendor', function (req, res, next) {
    var filename = req.body.filename;
    var file = req.body.file;
    fileBuffer = decodeBase64Image(file);

    request({
        url: "http://myvendorapi/ws/endpoint",
        method: "POST",
        headers: {
            'contentType': fileBuffer.type
        },
        body: fileBuffer.data
    }, function (error, response, body) {
        console.log(response);
    });
})

// Decode file for upload
function decodeBase64Image(dataString) {
    var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/),
        response = {};

    if (matches.length !== 3) {
        return new Error('Invalid input string');
    }

    response.type = matches[1];
    response.data = new Buffer(matches[2], 'base64');

    return response;
}

I can POST using AJAX on the front end, but because of CORS and the vendor blocking all but server side calls to the endpoints (and they don't have JSONP), I can't use this. They are allowing my IP through for testing purposes so only I can make this work from my machine:

var send = function (blob) {
 var fileTime = Date.now();
            var myFileName = $scope.productCode + fileTime;
            $scope.filenameForVendor = myFileName;
            var filename = $scope.filenameForVendor;
            var formdata = new FormData();
            formdata.append('File1', blob, filename);

            $.ajax({
                url: 'http://myvendorapi/ws/endpoint',
                type: "POST",
                data: formdata,
                mimeType: "multipart/form-data",
                processData: false,
                contentType: false,
                crossDomain: true,
                success: function (result) {
                    console.log("Upload to Vendor complete!");

// rest of code here/including error close out
}

 var bytes = atob(dataURL.split(',')[1])
        var arr = new Uint8Array(bytes.length);
        for (var i = 0; i < bytes.length; i++) {
            arr[i] = bytes.charCodeAt(i);
        }
        send(new Blob([arr], { type: 'image/png' }));

Update:

I realized that contentType should be 'content-type'. When I did this, it creates an error of no boundary specified as I am trying multipart-form data (which I did all wrong). How can I pass formData to Node for uploading?

Update 2:

Per the advice offered, I tried using multer but am getting an ReferenceError: XMLHttpRequest is not defined.

Client side:

   var fileTime = Date.now();
            var myFileName = $scope.productCode + fileTime;
            $scope.filenameForVendor = myFileName;
            var filename = $scope.filenameForVendor;
            var formdata = new FormData();
            formdata.append('File1', blob, filename);

            $http.post('/postVendor', formdata, { transformRequest: angular.identity, headers: { 'Content-Type': undefined } }).success(function (data) {

Server side:

app.post('/postVendor', function (req, res, next) {
    var request = new XMLHttpRequest();
    request.open("POST", "http://myvendorapi.net/ws/endpoint");
    request.send(formData);
})

Upvotes: 1

Views: 270

Answers (1)

m1gu3l
m1gu3l

Reputation: 773

Why do you base64 encode the file?

You can upload raw file to your Node using FormData and you will not have to decode anything.

Front end

...
var request = new XMLHttpRequest(); 
request.open('POST', 'http://node.js/method'); 
request.send(formData); // vanilla 

--- or ---

...
$http.post('http://node.js/method', formData, { 
  transformRequest: angular.identity, 
  headers: {'Content-Type': undefined} 
}); // angular

Back end

Just install request.

...
var request = require('request');
app.post('/method', function (req, res, next) {
  // if you just want to push request you don't need to parse anything
  req.pipe(request('http://vendor.net')).pipe(res);
}) // express

Upvotes: 1

Related Questions