Closed HugoMag closed 11 years ago
Hello again,
I've launched the simple example has a standalone server and its working.
I've also tried to use the simple example inside a page in my server but it does not work. From what I gathered this happens when I use connect-mongo as the session store. Here is the code to reproduce the error:
var http = require( 'http' ),
formaline = require( 'formaline' ),
connect = require( 'connect' ),
fs = require( 'fs' ),
log = console.log,
dir = '/tmp/';
var express = require('express')
extras = require('express-extras'),
path = require('path'),
mongoose = require('mongoose'),
url = require('url'),
util = require('util'),
DEBUG = true;
var app = express.createServer();
//save sessions in mongodb.
var MongoStore = require('connect-mongo');
var sessionStore = new MongoStore({db: "app" });
// Configuration
app.configure(function(){
app.use(express.methodOverride());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'aaa', store: sessionStore}));
app.use(app.router);
app.set('view engine', 'jade');
});
app.configure('development', function(){
app.use(express.static(__dirname + '/public'));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.get('/test/', function (req, res, next) {
getHtmlForm(req, res, next);
});
app.post('/test/post', function (req, res, next) {
handleFormRequest(req, res, next);
});
app.post('/test/upload', function (req, res, next) {
handleFormRequest(req, res, next);
});
getHtmlForm = function ( req, res, next ) {
if ( req.url === '/test/' ) {
log( ' -> req url :', req.url );
res.writeHead( 200, { 'content-type' : 'text/html' } );
res.end( '<html><head>\
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> \
</head><body>\
<style type="text/css">\
label,input { display: block; width: 236px; float: left; margin: 2px 4px 4px 4px; }\
label { text-align: center; width: 110px; color: #444; background-color: #f0f0f0; border: 1px solid #a0a0a0; padding: 1px; font-size: 14px; }\
form { margin-bottom: 10px; border: 1px solid #b0b0b0; padding: 16px; height: 200px;}\
form#mufile{ width: 380px; } form#simple{ width: 380px; } form#mframe{ width: 380px; }\
br { clear: left;}\
</style>\
<br/>\
<b>Simple Url Encoded Post:</b><br/><br/>\
<form id="simple" action="/test/post" method="post">\
<label for="sfield1">simplefield1</label> <input type="text" name="simplefield1" id="sfield1"/><br/>\
<label for="sfield2">simplefield2</label> <input type="text" name="simplefield2" id="sfield2"/><br/>\
<label for="sfield3">simplefield2</label> <input type="text" name="simplefield2" id="sfield3"/><br/>\
<label for="sfield4">simplefield3</label> <input type="text" name="simplefield3" id="sfield4"/><br/>\
<label for="sfield5">simplefield3</label> <input type="text" name="simplefield3" id="sfield5"/><br/>\
<label for="sfield6">simplefield3</label> <input type="text" name="simplefield3" id="sfield6"/><br/>\
<input type="submit" value="Submit" id="submit1">\
</form><br/>\
<b>Multiple File Upload:</b><br/><br/>\
<form id="mufile" action="/test/upload" enctype="multipart/form-data" method="post">\
<label for="id1">demotitle1</label> <input type="text" name="demotitle1" id="id1"/><br/>\
<label for="id2">multiplefield1</label> <input type="file" name="multiplefield1" multiple="multiple" id="id2"><br/>\
<label for="id3">demotitle2</label> <input type="text" name="demotitle2" id="id3"><br/>\
<label for="id4">multiplefield2</label> <input type="file" name="multiplefield2" multiple="multiple" id="id4"><br/>\
<label for="id5">demotitle3</label> <input type="text" name="demotitle3" id="id5"><br/>\
<label for="id6">multiplefield2</label> <input type="file" name="multiplefield3" multiple="multiple" id="id6"><br/>\
<input type="submit" value="Upload" id="upload1"/>\
</form><br/>\
<b>Iframe Multiple File Upload:</b><br/><br/>\
<form id="mframe" action="/test/upload" method="post" enctype="multipart/form-data" target="iframe" >\
<label for="ffield1">iframefield1</label> <input type="text" name="iframefield1" id="ffield1"/><br/>\
<label for="ffield2">iframefile1</label> <input type="file" name="iframefile1" multiple src="" frameborder="1" id="ffield2"/><br/>\
<label for="ffield3">iframefield2</label> <input type="text" name="iframefield2" id="ffield3"/><br/>\
<label for="ffield4">iframefile2</label> <input type="file" name="iframefile2" multiple src="" frameborder="1" id="ffield4"/><br/>\
<label for="ffield5">iframefield2</label> <input type="text" name="iframefield2" id="ffield5"/><br/>\
<label for="ffield6">iframefile2</label> <input type="file" name="iframefile2" multiple src="" frameborder="1" id="ffield6"/><br/>\
<input type="submit" value="Upload" id="upload2"/>\
</form>\
<iframe name="iframe" width="100%" height="600px"></iframe>\
</form>\
</body></html>'
);
} else {
next();
}
},
handleFormRequest = function ( req, res, next ) {
var receivedFields = {},
form = null,
currFile = null,
config = {
// default is false -->
holdFilesExtensions : !false,
// specify a path, with at least a trailing slash
// default is /tmp/ -->
uploadRootDir : dir,
// default is false
// to create and check directories existence in the sync way
mkDirSync : false,
// retrieve session ID for creating unique upload directory for authenticated users
// the upload directory gets its name from the returned session identifier,
// and will remain the same across multiple posts ( for the authenticated user with this session identifier )
// this function have to return the request property that holds session id
// the returned session id param, must contain a String, not a function or an object
// the function takes http request as a parameter at run-time
getSessionID : function ( req ) {
return "ola";
},
// default is 120000 milliseconds ( default nodeJS timeout for connection requests )
// the client connection is closed after the specified milliseconds ( minimum is 100 millisecs )
requestTimeOut : 5000, // 5 secs
// default is true
// when a fatal exception was thrown, the client request is resumed instead of immediately emitting 'loadend' event
// if false, the client request will be never resumed, the 'loadend' event will be emitted and the module doesn't handle the request anymore
resumeRequestOnError : true,
// default is false
// return sha1 digests for files received?
// turn off for better perfomances
sha1sum : false,
// switch on/off 'fileprogress' event
// default is false
// it serves to monitor the progress of the file upload
// and also to move the data to another stream, while the file is being uploaded
emitFileProgress : false,
// switch on/off 'progress' event
// default is false, or integer chunk factor,
// every n chunk emits a dataprogress event: 1 + ( 0 * n ) 1 + ( 1 * n ), 1 + ( 2 * n ), 1 + ( 3 * n ),
// minimum factor value is 2
emitProgress : false, // 3, 10, 100
// max bytes allowed for file uploads ( multipart/form-data ), it is a writing threshold, this is the max size of bytes written to disk before stopping
uploadThreshold : 1024 * 1024 * 1024 ,// bytes
// max bytes allowed for serialized fields, it limits the parsing of data received with serialized fields ( x-www-urlencoded )
// when it was exceeded, no data was returned
serialzedFieldThreshold : 1024 * 1024 * 1024,
// max bytes allowed for a single file
maxFileSize : 1024 * 1024 * 1024, // bytes, default 1GB
// default is false, bypass content-length header value ( it must be present, otherwise an 'error'->'header' will be emitted ),
// also if it exceeds max allowable bytes; the module continues to write to disk until |uploadThreshold| bytes are written.
// if true -> when headers content length exceeds uploadThreshold, module stops to receive data
checkContentLength : false,
// default is false
// remove file not completed due to uploadThreshold,
// if true formaline emit fileremoved event,
// otherwise return a path array of incomplete files
removeIncompleteFiles : false,
// default is 'debug:off,1:on,2:on,3:off,4:off,console:on,file:off,record:off';
// enable various logging levels
// it is possible to switch on/off one or more levels at the same time
// debug: 'off' turn off logging
// file: 'on' --> create a log file in the current upload directory with the same name and .log extension
// console: 'off' --> disable console log output
// record: 'on' --> record binary data from client request
// See the Readme!
logging : 'debug:on,1:on,2:off,3:off,4:off,console:on,file:off,record:off', // <-- turn off 2nd level to see only warnings, and parser overall results
// listeners
listeners : {
'message' : function ( json ) {
},
'error' : function ( json ) { // json:{ type: '..', isupload: true/false , msg: '..', fatal: true/false }
},
'abort' : function ( json ) {
},
'timeout' : function ( json ) {
},
'loadstart' : function ( json ){
},
'fileprogress' : function ( json, payload ) {
// json is the same for 'load' event ( when a file was received, see Readme ) ,
// 'payload' is a binary Buffer
// you can direct the data payload to another stream, while the file is being uploaded
/** /
if( currFile === null ) {
currFile = new fs.WriteStream( json.value.path + '*' );
}
currFile.write( payload );
/**/
},
'progress' : function ( json ) {
},
'load' : function ( json ){
currFile = null;
},
'loadend' : function ( json, res, cback ) {
log( '\n\033[1;32mPost Done..\033[0m' );
// log( '\n JSON -> \n', json, '\n' );
res.writeHead( 200, { 'content-type' : 'text/plain' } );
res.write( '-> ' + new Date() + '\n' );
res.write( '-> request processed! \n' );
res.write( '\n-> stats -> ' + JSON.stringify( json.stats, null, 4 ) + '\n' );
res.write( '\n Initial Configuration : ' + JSON.stringify( form.initialConfig, function ( key, value ) {
if ( typeof value === 'function' ) {
return '..';
}
return value;
}, 4 ) + '\n' );
res.write( '\n-> fields received: [ { .. } , { .. } ] \n ****************\n' + JSON.stringify( json.fields, null, 1 ) + '\n' );
res.write( '\n-> files written: [ { .. } , { .. } ] \n **************\n ' + JSON.stringify( json.files, null, 1 ) + '\n' );
if ( form.removeIncompleteFiles ) {
res.write( '\n-> partially written ( removed ): [ { .. } , { .. } ] \n *****************\n'+ JSON.stringify( json.incomplete, null, 1 ) + '\n' );
} else {
if ( json.incomplete.length !== 0 ) {
res.write( '\n-> partially written ( not removed ): \n *****************\n' + JSON.stringify( json.incomplete, null, 1 ) + '\n' );
}
}
res.end();
try {
cback();
} catch ( err ) {
log( 'error', err.stack );
}
}
}
}; //end config obj
if ( ( req.url === '/test/upload' ) || ( req.url === '/test/post' ) ) {
log( ' -> req url :', req.url );
form = new formaline( config ) ;
form.parse( req, res, hi );
} else {
if ( req.url === '/favicon.ico' ) { // short-circuit annoying favicon requests
res.writeHead( 200, { 'Content-Type' : 'image/x-icon' } );
res.end();
} else {
log( ' -> req url 404 error :', req.url );
res.writeHead( 404, { 'content-type' : 'text/plain' } );
res.end( '404' );
}
}
},
hi = function () {
form = null;
console.log( '\n\033[1;33mHi!, I\'m the callback function!\033[0m' );
};
if (!module.parent) {
app.listen(3000);
console.log("Express server listening on port %d", app.address().port)
}
I'm using nodeJS v0.4.1, connect 1.7.1 and connect-mongo 0.1.5.
Best regards, Hugo
Hi, I have the same error, but only when I upload some files...
Thanks for helping! Philippe
I am having some issues with express as well :/ This is the error I get while parsing upload if it comes from Express routing:
{"isupload":true,"msg":"req.headers[..] not found, or HTTP method not handled","fatal":true,"type":"headers"}
and this is a simple code i'm using:
app.post('/up', function(req, res) {
form = new formaline({});
form.on('error', function(json) {
console.log('error: ' + JSON.stringify(json));
});
form.parse(req, res, function() {
console.log('parsed');
});
});
I'm having the same issue as matylla, again, with the Express routing
I finally switched to connect-form, which works perfectly!
I recently talked to TJ (express author) and he pointed me to the simple solution - deleting whole object responsible for mutlipart parsing:
delete express.bodyParser.parse['multipart/form-data'];
After this, everything works like a charm.
I will make the switch too. If this is any use, I get the following error on submitting any type of form inputs:
formaline, event "headersexception" --> {"isupload":false,"msg":"req.headers[..] not found, or HTTP method not handled","fatal":true}
Here's console.log of req.headers:
host: 'localhost:3000', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_68) AppleWebKit/534.51.22 (KHTML, like Gecko) Version/5.1.1 Safari/534.51.22', accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,/_;q=0.8', 'accept-language': 'en-us', 'accept-encoding': 'gzip, deflate', cookie: 'utmz=111872281.1319622455.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); utma=111872281.1162108877.1319622455.1321483235.1321793892.3; connect.sid=zBWDRfvtpNjRSiccgMulJmRg.zd3oU4UG8g1lnDyWWEInppFXuQGIkh3VAA8xoDZpT5s', connection: 'keep-alive' }
I just disabled express.bodyParser and it now works!
Thanks for that matylla, I hadn't refreshed the page hence didn't see your comment. I'll give it a go now..
Is there a way to temporarily disbale bodyParser rather than delete it?
Hey guys, I was also having the same issue and I am not using any framework. It was just happening because I was throwing the same event two times.
I just debug my code using console.log("is Request Complete" + req.complete); to find out the exact point of error and finally I solve my issue. You can also debug to sort out your issue. Hope this helps. :)
Isnt there any way to get it working with bodyParses enabled?
Which version of express are you using? The bodyParser middleware now returns a req.files
object containing your files. Please see http://tjholowaychuk.com/post/12943975936/connect-1-8-0-multipart-support.
If you're after upload progress bars, I found this article particularly useful http://www.matlus.com/html5-file-upload-with-progress/
express: "version": "2.5.8" connect: "version": "1.8.6"
but im using formaline not formidable, or it will be the same?
It sounds like the issue here was just a difference in the version of express.
However, know that formaline v2.0.0 is out. The API has been simplified and it has undergone some pretty decent testing that fixes most of the previous issues.
Hi,
I'm trying to use formaline with the jquery File-Upload plugin https://github.com/blueimp/jQuery-File-Upload but I always keep getting the error "Failed to parse request data . Request was empty or already completed". I can see in Firebug that the request is made as "multipart/form-data" and that the files are sent. I also see that the files dir is created.
Can you help me?
Here is the code:
jade file:
div#fileupload form(action='/upload/', multipart=true, enctype="multipart/form-data" ) div.fileupload-buttonbar label.fileinput-button span Add files... input(id="file_upload", name="files[]", type="file", multiple) button.start(type="submit") Start upload button.cancel(type="submit") Cancel upload button.delete(type="submit") Delete files
albums.js:
function add_album_image(req, res, next) {
}
Thanks. Best regards, Hugo