0

I am trying to pass some data to my node.js server with an ajax request.

Unfortunately I my server logs an empty object and my ajax call doesn't log any success nor error.

Here's the snippet of my code:

    var fd = new FormData();
    function appendPicture(){
      fd.append('picture_data', that.state.newFeedMediaData);
      fd.append('content', that.state.newFeedContent);
      fd.append('img_inline_style', img_inline);
    }

    var p1 = Promise.resolve(appendPicture());
    p1.then(function(v){
      console.log(fd);
      $.ajax({
        url: '/api/setNewFeedPost',
        data: fd,
        processData: false,
        contentType: false,
        enctype: 'multipart/form-data',
        type: 'POST',
        success: function(data){
          console.log("success");
        },
        error: function(data){
          console.log("error");
        }
      });
    });

img_inline_style contains the following object:

{Filter: "grayscale(0%) brightness(100%) contrast(100%) sepia(0%)"
WebkitFilter: "grayscale(0%) brightness(100%) contrast(100%) sepia(0%)"
backgroundImage: ""
backgroundPositionY: -66
backgroundSize: "cover"
height: "100%"}

Even if there would be something wrong inside my sendObj I don't think thats the issue since even when I try to send some simple string like "test" the request just doesn't happen.

Why would this be?

Additional info:

On my node.js server side im simply logging the received data which gets printed out simply like an empty object

Received data: {}

I am using node.js with express and my server side render script of an ajax post in my api file looks as following:

router.post('/setNewFeedPost', function(req, response, next){
  console.log("Set new Feedpost content: ",req.body);
});
noa-dev
  • 3,561
  • 9
  • 34
  • 72
  • Looks okay to me. Any other errors? – Praveen Kumar Purushothaman Jan 01 '16 at 17:18
  • No errors in my browser console and no errors on my server logs – noa-dev Jan 01 '16 at 17:20
  • In your Network Tab, does it even send a request to `/api/setNewFeedPost`? – Praveen Kumar Purushothaman Jan 01 '16 at 17:20
  • Yes it does. I also log the response on my server but its just an empty object – noa-dev Jan 01 '16 at 17:21
  • @PiyushAghera - Because it contains a form Data object as well as other stuff. – noa-dev Jan 01 '16 at 17:22
  • @noa-dev This might work. Try the shorthand function and let me know what happens. See my answer. – Praveen Kumar Purushothaman Jan 01 '16 at 17:27
  • @noa-dev Ah... Looks like something else is stopping. Kindly show us your HTML also. – Praveen Kumar Purushothaman Jan 01 '16 at 17:31
  • I believe you have to use a FormData object, or an object that does not contain complicated objects (ie object containing a formdata object). Check the request header and look for the `Request Payload` when i tested with a object containing a formdata object it just had `[object Object]` but had an actual payload when using just a formdata object – Patrick Evans Jan 01 '16 at 17:32
  • Everything is written in React so I don't have any HTML. I also don't think it's somewhere there since even when I try to send a simple string instead of the object I just get an empty response on my server – noa-dev Jan 01 '16 at 17:32
  • @PatrickEvans yes. It says [object Object] – noa-dev Jan 01 '16 at 17:33
  • Try using just a FormData object (ie put everything in it) and use that as the `data` option that should solve the server not showning anything. Though your current settings should not keep jQuery from running the success/error callbacks – Patrick Evans Jan 01 '16 at 17:34
  • @PatrickEvans just tried it out. Same result as in the previous way. No success nor error log and my server responds with an empty {} – noa-dev Jan 01 '16 at 17:43
  • Would you mind elaborating on your server side a bit? Which framework and also please show the part which should log the result on the server side. Another suggestion would be to drop down a level and try posting via a raw XMLHttpRequest – Luis Nell Jan 02 '16 at 17:33

2 Answers2

1

Taking a wild guess here, but you might be missing the correct middleware to handle multipart requests. Sadly, express can be quite daunting and this is one of those times.

As can be seen in How to get POST a query in Express.js/Node.js?, you need to add various middlewares to support various types of request bodies. As already pointed out there, you need to have body-parser for parsing request bodies. However since you are using multipart, you can't simply rely on body-parser. Here's an excerpt from their current README:

Node.js body parsing middleware.
This does not handle multipart bodies, due to their complex and typically large nature.

It goes on to list various alternatives. One of them being express' own multer. Their README is quite nice, however for the sake of completeness I decided to put together a small example which reflects your use case slightly:

app.js

var console = require("console");
var path = require('path');

var multer = require('multer');
var express = require('express');

var app = express();
// using path with __dirname is essential so you avoid the common pitfall of using
// relative paths, where you can never be sure if they are calculated 
// from the current working directory or the directory of the file.
var upload = multer({dest: path.join(__dirname, 'uploads')});

// upload.any() is merely used for demonstration purposes and
// I do not recommend using this in production! See their README.
app.post('/save', upload.any(), function(req, res) {
    console.log('Files', req.files);  // All files are in here.
    console.log('Body Data', req.body);  // The rest of the data here.
    // It is important to answer your client with something.
    // Otherwise the client will never know you've received anything
    // (resulting in a "pending" state and timeout errors).
    res.send('win');
});

index.html

<form action="#">
    <input type="file" name="foo_img">
    <button type="submit">Lets go</button>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
    var img_inline_style = {
        backgroundImage: "",
        backgroundPositionY: -66,
        height: "100%"
    };

    $('form').submit(function(event) {
        event.preventDefault();

        // This is basically what you are doing, I guess.
        var data = new FormData();
        data.append('picture_data', $('input').get(0).files[0]);
        data.append('content', 'foobarbarz');
        // As correctly pointed out by Quentin's answer, you can't simply
        // send objects. You need to transform them into a string. Here
        // I'm doing this by converting the object into a string via JSON.
        data.append('img_inline_style', JSON.stringify(img_inline_style));

        $.ajax({
            url: '/save',
            data: data,
            processData: false,
            contentType: false,
            enctype: 'multipart/form-data',
            type: 'POST',
            success: function(data){
                console.log("success");
            },
            error: function(data){
                console.log("error");
            }
         });
    });
</script>

Result

When running this, one can observe the following output on the server:

Files [ { fieldname: 'picture_data',
    originalname: 'IMG_6365.JPG',
    encoding: '7bit',
    mimetype: 'image/jpeg',
    destination: '/Users/luis/Desktop/test/uploads',
    filename: '743c2599a93761a347ce0951ec746927',
    path: '/Users/luis/Desktop/test/uploads/743c2599a93761a347ce0951ec746927',
    size: 1561538 } ]
Body Data { content: 'foobarbarz',
  img_inline_style: '{"backgroundImage":"","backgroundPositionY":-66,"height":"100%"}' }

As you can see the file I selected is there and the rest of the data too. Success!

Hope this helps :)

Community
  • 1
  • 1
Luis Nell
  • 534
  • 4
  • 12
0

The sendObj content looks like this:

content: "adasd"
img_inline_style: Object
picture_data: FormData
  1. Pass the form data object to data: directly. Don't wrap it in another element. You can't pass a plain object to data: while telling it not to process it, the results won't be useful. You can pass a FormData object directly to it, that's how you use FormData objects with jQuery.
  2. Append the content to it
  3. I have no idea what img_inline is, but you need to convert it to a format you can express as a string or strings. e.g. loop over each value and append each of them, or convert to JSON and append that
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • I have updated my Question with the content of img_inline_style – noa-dev Jan 02 '16 at 17:55
  • @noa-dev — So look over each value and append each of them in turn, as I said. – Quentin Jan 02 '16 at 17:55
  • I have updated my Question with the new script. I append all 3 values into the fd object. Still the same result with the empty server log. Do I need to encode the img style object first in order to make it work? Maybe an object within an object cant be sent – noa-dev Jan 02 '16 at 17:59
  • What does the body of the request look like in the network tab of your developer tools? (And what does your updated code look like?) – Quentin Jan 02 '16 at 20:38