Every time I try and upload I get: 'parser error, 0 of 1460 bytes parsed' #34

Closed
tglines opened this Issue Jan 19, 2011 · 11 comments

Projects

None yet

7 participants

@tglines
tglines commented Jan 19, 2011

Running the form example used to work, it now no longer does? I get this error:

events:12
    throw arguments[1];
                   ^
Error: parser error, 0 of 1460 bytes parsed
at IncomingForm.write (/usr/local/lib/node/.npm/formidable/0.9.11/package/lib/formidable/incoming_form.js:123:17)
at IncomingMessage.<anonymous> (/usr/local/lib/node/.npm/formidable/0.9.11/package/lib/formidable/incoming_form.js:73:12)
at IncomingMessage.emit (events:31:17)
at HTTPParser.onBody (http:100:23)
at Stream.ondata (http:763:22)
at IOWatcher.callback (net:494:29)
at node.js:773:9
@tglines
tglines commented Jan 19, 2011

A note to anyone else who comes across this one ... and I hope google spiders this one better ....

Make sure you're not doing any mongodb lookups in node (like account data) before you get a handle on the upload. Simply move the account stuff into the callback and you'll be fine.

@felixge
Owner
felixge commented Jan 23, 2011

Yeah, the problem is that req.pause() doesn't work like one would expect it to at this point, but ryan is fixing it. There is nothing formidable can do about this problem for now.

@outbounder

Hi there,
I've managed to workaround the issue like this:

http.createServer(function(req, res) {
    var chunks = [];
    var dataBufferedHandler = function(chunk) {
         chunks.push(chunk);
    };

    req.on('data', dataBufferedHandler);

    doSomethingWithTimeDelayAndInvoke(function() {
          req.removeListener("data", dataBufferedHandler);

          // handle any incoming chunks
          formidable.parse(req, function() {...});

          // pass to formidable all missed chunks
          for(var i in chunks)
               req.emit('data', chunks[i]);
    });
}).listen(8080);

It is not good solution, but an workaround. It works as expected at least within the integration tests. The only drawback is that if "doSomethingWithTimeDelayAndInvoke" takes too much time, then 'chunks' array will get too big and possibly out of memory. However for atomic operations using mongodb it works just fine :)

@Tug
Tug commented Apr 23, 2011

Thanks, your workaround worked fine for me.
I added a call to req.pause to ensure that it is not receiving new chunks. This way, it should work with long async calls (and no memory issue) :

http.createServer(function(req, res) {
    var chunks = [];
    var dataBufferedHandler = function(chunk) {
         chunks.push(chunk);
    };

    req.on('data', dataBufferedHandler);
    req.pause();

    doSomethingWithTimeDelayAndInvoke(function() {
          req.resume();
          req.removeListener("data", dataBufferedHandler);

          // handle any incoming chunks
          formidable.parse(req, function() {...});

          // pass to formidable all missed chunks
          for(var i in chunks)
               req.emit('data', chunks[i]);
    });
}).listen(8080);

It seems the problem with req.pause is that it pauses the stream but does not buffer any data, so if a chunk is being received and pause has just been called, it will still emit a 'data' event.

@tommedema

Shouldn't this issue be open considering it is still of effect?

@Tug
Tug commented Apr 23, 2011

Maybe. And also merged with #30 and #31.
But this can't be fixed in formidable.

Or perhaps the workaround can be implemented in formidable ?
like formidable.pause() and formidable.resume()
But still this pause function would need to be called synchronously and I'm not sure this is a wanted behavior (for instance, express does some async before calling the routing callback (like loading session from the datastore))

edit: ok apparently express pauses the request when fetching the session so it's consistent.

@Tug
Tug commented Apr 23, 2011

pause and resume are implemented in formidable but maybe they should be moved out of the parse function ?

edit : ex :

var form = new formidable.IncomingForm(req);
form.pause();
doSomethingWithTimeDelayAndInvoke(function() {
    form.resume();
    form.parse(function(err) {
     // end
    });
});
@felixge
Owner
felixge commented Apr 27, 2011

Tug: The code snippet you pasted should work as expected.

@tarangill

This issue is still there. I am not even using MongoDB. I am using RailwayJS framework, don't really know what IO operations it does. But the thing is, I am getting these errors just randomly. About 10% of the time. I tried using the snippet by Tug, but the issue remains.

@Tug
Tug commented Apr 5, 2012

I can only guess that RailwayJS is doing async calls before executing your script. You should try to hook to the request event directly.

Btw, I have written a simple middleware which use formidable to control a multipart file upload stream, maybe it can help you.. https://github.com/Tug/upload-middleware

@santiago

Thanks :)

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment