I am trying to make an Image/File upload form using NodeJs and Formidable. I'm not using express. Just formidable. But anyways, I tried the most common scripts with formidable, and none have worked.My code is basically exactly the same as the one from this tutorial: http://justinkjchang.wordpress.com/2013/11/08/image-uploader-using-node-js/
There are a lot of these tutorials around, and i've seen almost the exact same thing in some books, or videos, and they all seem to work, except mines. I have Installed formidable, and I have the latest version of both that, and Node. I'm on a mac too. When I try to upload, it'll go through the form.parse and everything, but when it tries to write the file, it throws this error:
/Users/USER/Documents/Node/requestHandlers.js:42
fs.rename(files.upload.path, "/tmp/test.png", function (error) {
^
TypeError: Cannot read property 'path' of undefined
I'm new to Nodejs, so any kind of help would be nice. I tried doing file.write too, and it still throws the same error. Any help would be gladly appreciated (:
Updated with code:
var exec = require("child_process").exec;
var qs = require("querystring"),
fs = require("fs"),
formidable = require("formidable"),
url = require( "url" );
function start(response, request) {
/*
var fileName = "start.html"
var localPath = __dirname;
var mimeType = "text/html";
var name = localPath + "/" + fileName;
getFile(name, response, mimeType);
console.log("Request handler 'start' was called.");
console.log("Serving File: " + name);
*/
var body = '<html>'+
'<head>'+
'<meta http-equiv="Content-Type" '+
'content="text/html; charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" enctype="multipart/form-data" '+
'method="post">'+
'<input type="file" name="upload" multiple="multiple">'+
'<input type="submit" value="Upload file" />'+
'</form>'+
'</body>'+
'</html>';
console.log( "Request for 'start' is called." );
response.writeHead( 200, { "Content-Type" : "text/html" } );
response.end( body );
}
function upload(response, request) {
console.log("Request handler 'upload' was called.");
console.log( "Preparing upload" );
var form = new formidable.IncomingForm();
form.parse(request, function(error, fields, files){
if(error){
console.log(error);
console.log("Dun Goofed");
}
console.log("parsing done");
fs.rename(files.upload.path, "/tmp/test.png", function (error) {
if (error) {
fs.unlink("/tmp/test.png");
fs.rename(files.upload.path, "/tmp/test.png");
}
});
/* fs.rename(files.upload.path, "/tmp/test.png", function(err){
if(err){
fs.unlink("/tmp/test.png");
fs.rename(files.upload.path, "/tmp/test.png");
}
}); */
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Received image: <br/>");
response.write("<img src='./show' />");
response.end();
});
}
exports.start = start;
exports.upload = upload;
//exports.show = show;
I Omitted some parts because they have nothing to do with the file upload, please excuse the comments too, just old code. I also do not have a /show function because I erased it temporarily.
Also Here are the errors I get in the console. One of the errors is because the upload cancels. After I enter the file I want to upload, the browser just sits there for a while and waits for request for the server, and in the console, it just stops before form.parse, and sits there doing nothing for about a minute, then it rolls out all the errors.
Web Server started on 127.0.0.1:8888
Request for / received.
About to route a request for /
Served a request for /
Request for 'start' is called.
Request for /upload received.
Received POST data chunk
About to route a request for /upload
Served a request for /upload
Request handler 'upload' was called.
Preparing upload
Successfully executes until here.
Then the browser waits for a while, and then It either pops up with no data received, or the webpage is unavailable, and then these errors come up in the console.
{}
[Error: Request aborted]
Dun Goofed
parsing done
/Users/USER/Documents/Node/requestHandlers.js:50
fs.rename(files.upload.path, "/tmp/test.png", function (error) {
^
TypeError: Cannot read property 'path' of undefined
at /Users/USER/Documents/Node/requestHandlers.js:50:31
at IncomingForm.<anonymous> (/Users/USER/node_modules/formidable/lib/incoming_form.js:89:9)
at IncomingForm.EventEmitter.emit (events.js:95:17)
at IncomingForm._error (/Users/USER/node_modules/formidable/lib/incoming_form.js:272:8)
at IncomingMessage.<anonymous> (/Users/USER/node_modules/formidable/lib/incoming_form.js:107:12)
at IncomingMessage.EventEmitter.emit (events.js:92:17)
at abortIncoming (http.js:1911:11)
at Socket.serverSocketCloseListener (http.js:1923:5)
at Socket.EventEmitter.emit (events.js:117:20)
at TCP.close (net.js:465:12)
I have the same problem.
delete the code request.setEncoding("utf8"); in server.js
like this:
function start(route, handler) {
http.createServer(function(request, response) {
var postData = "";
var pathname = url.parse(request.url).pathname;
route(handler, pathname, response, request);
}).listen(8889);
}
Related
I'm trying to pass data from c# using console application to webpage using socket.io in real time
here is my c# code:
static void Main(string[] args)
{
int i = 0;
while(true)
{
//String data = Console.ReadLine();
String data = i.ToString();
if(data.Equals("exit", StringComparison.OrdinalIgnoreCase)) break; //If the user types "exit" then quit the program
SendData("127.0.0.1", 41181, data); //Send data to that host address, on that port, with this 'data' to be sent
//Note the 41181 port is the same as the one we used in server.bind() in the Javascript file.
System.Threading.Thread.Sleep(50); //Sleep for 50ms
i++;
}
}
public static void SendData(string host, int destPort, string data)
{
IPAddress dest = Dns.GetHostAddresses(host)[0]; //Get the destination IP Address
IPEndPoint ePoint = new IPEndPoint(dest, destPort);
byte[] outBuffer = Encoding.ASCII.GetBytes(data); //Convert the data to a byte array
Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //Create a socket using the same protocols as in the Javascript file (Dgram and Udp)
mySocket.SendTo(outBuffer, ePoint); //Send the data to the socket
mySocket.Close(); //Socket use over, time to close it
}
this is app.js
var app = require('http').createServer(handler);
var io = require('socket.io').listen(app);
var fs = require('fs');
var mySocket = 0;
app.listen(3000); //Which port are we going to listen to?
function handler (req, res) {
fs.readFile(__dirname + '/index.html', //Load and display outputs to the index.html file
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
console.log('Webpage connected'); //Confirmation that the socket has connection to the webpage
mySocket = socket;
});
//UDP server on 41181
var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("message", function (msg, rinfo) {
console.log("Broadcasting Message: " + msg); //Display the message coming from the terminal to the command line for debugging
if (mySocket != 0) {
mySocket.emit('field', "" + msg);
mySocket.broadcast.emit('field', "" + msg); //Display the message from the terminal to the webpage
}
});
server.on("listening", function () {
var address = server.address(); //IPAddress of the server
console.log("UDP server listening to " + address.address + ":" + address.port);
});
server.bind(41181);
finally this is index.html
<html>
<head>
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
</head>
<body>
<script>
var socket = io();
socket.on('field', function (data) {
$("#field").html(data);
});
</script>
Data from C#: <div id="field"></div>
</body>
</html>
I used this article to implement it, everything, seems work fine for example when I send data to console of node.js it display it but as soon as I run the page (localhost:3000) after several printing "webpage connected" it shows this error in my console:
nodemon app crashed - waiting for file changes
can someone give me a solution?
this my result picture
Error may occure on a different levels. I see that you are not listenning socket errors, both for server and io.
Both of them are based on EventEmiter approach, so both have error event to listen.
Try to listen all possible error places, this will give you additional infromation on why your app crashed.
server.on("error", err => console.error("server error occured", err));
io.on("error", err => console.error("io error occured", err));
Update
Replace in index.html script loading for socket.io with this.
<script src="/socket.io/socket.io.js"></script>.
Then, all re-connection issues should gone. I'm not pretty sure how it is working.
I am following the guide in the Node Beginner Book and have managed to get all the way through to the last section, Handling file uploads. This book focuses on JavaScript calling methods and using request and response with very little HTML included only as strings when necessary.
All my console.log statements are showing me the correct file path. But instead of displaying the image I get the following HTML line:
I think the problem is in this line in requestHandlers.js:
response.write("<img src='/show' />");
It is supposed to be calling the show function at the bottom of requestHandlers.js. Look at the Console output at the bottom of this post and you can see that execution never gets into the show function. Source code and Console output is below:
index.js
var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");
var handle = {};
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
handle["/show"] = requestHandlers.show;
server.start(router.route, handle);
server.js
var http = require("http");
var url = require("url");
function start(route, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(handle, pathname, response, request);
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
router.js
function route(handle, pathname, response, request) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname](response, request);
} else {
console.log("No request handler found for " + pathname);
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not found");
response.end();
}
}
exports.route = route;
requestHandlers.js
var querystring = require("querystring"),
fs = require("fs"),
formidable = require("formidable");
var path = require('path');
var file = path.join(__dirname, 'tmp', "test.png");
function start(response) {
console.log("Request handler 'start' was called.");
var body = '<html>'+
'<head>'+
'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" enctype="multipart/form-data" method="post">'+
'<input type="file" name="upload" multiple="multiple"/>'+
'<input type="submit" value="Upload file"/>'+
'</form>'+
'</body>'+
'</html>';
response.writeHead(200, {"Content-Type": "text/html"});
response.write(body);
response.end();
}
function upload(response, request) {
console.log("Request handler 'upload' was called.");
var form = new formidable.IncomingForm();
console.log("about to parse");
form.parse(request, function(error, fields, files) {
console.log("parsing done");
console.log("File = "+file);
fs.rename(files.upload.path, file, function (error) {
if(error) {
console.log("error");
fs.unlink(file);
console.log(file);
fs.rename(files.upload.path, file);
console.log(file);
}
});
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("received image:<br/>");
response.write("<img src='/show' />");
response.end();
});
}
function show(response) {
console.log("Request handler 'show' was called.");
response.writeHead(200, {"Content-Type": "image/png"});
fs.createReadStream(file).pipe(response);
}
exports.start = start;
exports.upload = upload;
exports.show = show;
Console output
C:\Users\pdl\Projects\TestSeparateJS>node index.js
Server has started.
Request for / received.
About to route a request for /
Request handler 'start' was called.
Request for /upload received.
About to route a request for /upload
Request handler 'upload' was called.
about to parse
parsing done
File = C:\Users\pdl\Projects\TestSeparateJS\tmp\test.png
error
C:\Users\pdl\Projects\TestSeparateJS\tmp\test.png
C:\Users\pdl\Projects\TestSeparateJS\tmp\test.png
You're sending the content as plaintext instead of HTML. So the browser never runs it as HTML. That's why you see the <img> text instead of an <img> tag being generated.
In your upload function change this:
response.writeHead(200, {"Content-Type": "text/plain"});
to this:
response.writeHead(200, {"Content-Type": "text/html"});
When using a newer version of node.js, you also might like to change the code files.upload.path into files.upload.filepath
So here is what I'm trying to achieve!
I want to create a very simple Node application where I can make use of the eval function by creating a input text box and a submit button. I want to be able to write things in the text box and when hitting submit to use the eval function to send this parameter to the server.
So if I write while(true) in the text box this should cause a DoS attack to the server, due to the eval vulnerability.
Here is my code so far (fix doesn't work properly)
var http = require("http");
var server = http.createServer(function(request, res) {
res.writeHead(200, {"Content-Type": "text/html"});
res.write("<html>");
res.write("<head>");
res.write("<title>Hello World Page</title>");
res.write("</head>");
res.write("<body>");
res.write("Enter Some text");
res.write('<input type="text" name="fname">');
res.write('<input type="submit" value="Submit")');
var parameter = eval(req.body.fname);
res.send(parameter);
res.write("</body>");
res.write("</html>");
res.end();
});
server.listen(1337);
console.log("Server is listening");
Any ideas on how to make this work?
First - here is a good post on the topic: Accessing the HTTP message body (e.g. POST data) in node.js
A couple of minor changes to your html:
I've added a form element with an action and method set to POST. You could use GET as well to avoid some of the req.on(...) logic below.
added closing bracket for the submit button - you had a typo with a paren
When reading posted form data, you will need to read all of the data coming in until it is complete. The req parameter is an event emitter so you would use:
req.on('data', function(chunk) {...}
req.on('end', function() {...}
To buffer up the incoming data then act on it when the end of the request is reached.
The form data is encoded, so you will need to parse it using the querystring module.
I've also added just enough error checking (and fixed a few naming bugs) to get the code to function at a basic level.
Code:
var http = require("http");
var querystring = require('querystring');
var util = require('util');
var server = http.createServer(function(req, res) {
var body = "";
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
console.log('POSTed: ' + body);
body = querystring.parse(body);
console.log('decoded: ' + util.inspect(body));
res.writeHead(200, {"Content-Type": "text/html"});
res.write("<html>");
res.write("<head>");
res.write("<title>Hello World Page</title>");
res.write("</head>");
res.write("<body>");
res.write("Enter Some text");
res.write('<form action="/" method="post">');
res.write('<input type="text" name="fname">');
res.write('<input type="submit" value="Submit">');
res.write('</form>');
if(body.fname) {
var parameter = eval(body.fname);
console.log(util.inspect(parameter));
if(parameter) {
res.write(parameter);
}
}
res.write("</body>");
res.write("</html>");
res.end();
});
});
server.listen(1337);
console.log("Server is listening");
link to article: http://www.html5rocks.com/en/tutorials/eventsource/basics/
The node.js SSE server is not working in that example. I end up with an open connection to /events, but no response is received by the browser.
sse-server.js
var http = require('http');
var sys = require('sys');
var fs = require('fs');
http.createServer(function(req, res) {
//debugHeaders(req);
if (req.headers.accept && req.headers.accept == 'text/event-stream') {
if (req.url == '/events') {
sendSSE(req, res);
} else {
res.writeHead(404);
res.end();
}
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(fs.readFileSync(__dirname + '/sse-node.html'));
res.end();
}
}).listen(8000);
function sendSSE(req, res) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
var id = (new Date()).toLocaleTimeString();
// Sends a SSE every 5 seconds on a single connection.
setInterval(function() {
constructSSE(res, id, (new Date()).toLocaleTimeString());
}, 5000);
constructSSE(res, id, (new Date()).toLocaleTimeString());
}
function constructSSE(res, id, data) {
res.write('id: ' + id + '\n');
res.write("data: " + data + '\n\n');
}
function debugHeaders(req) {
sys.puts('URL: ' + req.url);
for (var key in req.headers) {
sys.puts(key + ': ' + req.headers[key]);
}
sys.puts('\n\n');
}
sse-node.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
var source = new EventSource('/events');
source.onmessage = function(e) {
document.body.innerHTML += e.data + '<br>';
};
</script>
</body>
</html>
The problem was with the server. In my case I was using node with IIS using the iisnode node package. To solve this, I needed to configure iisnode in the web.config like so:
<iisnode flushResponse="true" />
After this, everything worked fine. Others with a similar issue may start here, but apache and nginx may have similar configuration requirements.
Why did you comment out the res.end() at the end of the sendSSE function? That's the method that actually sends the response to the browser.
I already try that code and is working for me, as you are not using ngnix, or any other server as proxy for your node instances I would believe that the problem is with your machine, if you have firewall or anti virus running, stop it, and try again or any other software that could be intercepting yours req and res.
Make sure you have saved the HTML file with same name as described sse-node.html in same directory. Other thing might be make sure 8000 port is open in your local machine no one is using it. or change the port and re-run sse-server.js. its working for me as is.
I faced the same issue. Nothing wrong with your code just Provide Full Resource Address in your HTML File.
var source = new EventSource('http://localhost:8000/events'); //true way
instead of
var source = new EventSource('/events'); //improper way
With the following Node.js architecture: index.js + server.js + router.js + requestHandlers.js
Am new to javascript application programming.. How does Node.js talk to MongoDB in the most basic way?
Is mongoose necessary? If so, what is a basic implementation?
requestHandlers.js:
var querystring = require("querystring"),
fs = require("fs");
function start(response, postData) {
console.log("Request handler 'start' was called.");
var body = '<html>'+
'<head>'+
'<meta http-equiv="Content-Type" '+
'content="text/html; charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" method="post">'+
'<textarea name="text" rows="20" cols="60"></textarea>'+
'<input type="submit" value="Submit text" />'+
'</form>'+
'</body>'+
'</html>';
response.writeHead(200, {"Content-Type": "text/html"});
response.write(body);
response.end();
}
function upload(response, postData) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("You've sent the text: "+
querystring.parse(postData).text);
response.end();
}
exports.start = start;
exports.upload = upload;
exports.show = show;
Im very new to nodejs myself so my answers may not be the most adequate but i think sending data to node would be done the same way its done in PHP, mostly ajax calls.
and to parse the submitted data, you can use (in node express), or using querystring as youve done.
app.use(express.bodyParser({ keepExtensions: true, uploadDir: __dirname + '/tmp', }));
and then access the submitted variables using request.body.yourvariable
and request.files for uploaded files.
and mongoose is not necessary, but its recommended.
It provides additional functionality to mongo.