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
Related
I'm working on a small website, I'm a beginner in javascript and nodejs, I create a small server with nodejs but I do not know how to load my file.js in the server help please.
this is my server :
enter code here
let http = require('http');
let fs = require('fs');
let path = require('path');
http.createServer(function(req, res)
{
if(req.url === "/")
{
fs.readFile("index.html", "UTF-8", function(err, html)
{
res.writeHead(200, {"Content-Type": "text/html"});
res.end(html);
});
}else if(req.url.match("\.css$"))
{
var cssPath = path.join(__dirname, '', req.url);
var fileStream = fs.createReadStream(cssPath, "UTF-8");
res.writeHead(200, {"Content-Type": "text/css"});
fileStream.pipe(res);
}else if(req.url.match("\.png$")){
var imagePath = path.join(__dirname, '', req.url);
var fileStream = fs.createReadStream(imagePath);
res.writeHead(200, {"Content-Type": "images/png"});
fileStream.pipe(res);
}else if (req.url.match("\.jpg$")) {
var imagePath = path.join(__dirname, '', req.url);
var fileStream = fs.createReadStream(imagePath);
res.writeHead(200, {"Content-Type": "images/jpg"});
fileStream.pipe(res);
}
else
{
res.writeHead(404, {"Content-Type": "text/html"});
res.end("No Page Found");
}
}).listen(3000, '127.0.0.1');
and this is a part from my javascript file
$(function(){
let navMain=document.querySelector('nav');
let ul=document.getElementById('mainUl');
let li=document.createElement('li');
let a=document.createElement('a');
let login=document.createTextNode('Login');
$(window).on('scroll',function(){
const navMainTopMesure=navMain.offsetTop;
if($(window).scrollTop() && window.scrollY>=navMainTopMesure){
$('nav').addClass('fixed');
a.appendChild(login);
li.appendChild(a);
ul.appendChild(li);
a.addEventListener('click',function(){
document.querySelector('.login').style.display='flex';
});
return 0;
}else{
$('nav').removeClass('fixed');
ul.removeChild(li);
}
})
});
$(function(){
window.addEventListener('click',function(e){
if(e.target == document.querySelector('.register')){
document.querySelector('.register').style.display='none';
}
})
window.addEventListener('click',function(e){
if(e.target == document.querySelector('.login') ){
document.querySelector('.login').style.display='none';
}
})
let date =new Date();
document.getElementById('date').innerHTML=date.toDateString();
document.querySelector('.sign-up').addEventListener('click',function(){
document.querySelector('.register').style.display='flex';
})
document.querySelector('.closeRegister').addEventListener('click',function(){
document.querySelector('.register').style.display='none';
})
document.querySelector('.sign-in').addEventListener('click',function(){
document.querySelector('.login').style.display='flex';
})
document.querySelector('.closeLogin').addEventListener('click',function(){
document.querySelector('.login').style.display='none';
})
$('.mobile-nav').on('click',function(){
$('.nav-main ul').toggleClass('drop');
$('.mobile-nav i').toggleClass('fa-times');
})
});
function smoothScroll(target,duration)
{
var target = document.querySelector(target);
var targetposition = target.getBoundingClientRect().top;
var startposition = window.pageYOffset;
var distance = targetposition-startposition;
var starttime = null;
i just want to execute my function in javascripte file in my server.
my probleme when i execute the html file on the localhost in the browser evry think is okey but any javascript event happend
What you want to do is create a folder in your main app directory, called 'frontend' or 'src' or 'public' and in that folder create the directory that will be used by your index.html file. Throw your JS file in there wherever you want it.
In your main server or app.js file for node, do app.use(express.static(path.join(__dirname, 'whatevernameyouchoseforyourfrontendfiles')));
And after you serve the initial HTML files every time your server gets a request for a file it will know where to look.
I'm creating a http server with JS and Node JS.
It consists of a form where you can input text that should be the pathname of a file. Once you press on submit button, it should show on webpage the content of that file.
I read the content of the file with function file(pathname) and return it as a String. Then I try to to show the content on webpage with:
response.write('File content: '+ string); but it shows 'File content: undefined'
I think my problem is on the response.write(), because when I use console.log() to show the file content is working correctly.
What I'm doing wrong?
Here is the code when you press on submit:
if(url_parts.pathname == '/submit') { //Processing the form content, if the relative URL is '/ submit'
var pathname=url_parts.query['name']; //Read the contents of the field (form) named 'name'
var string = file(pathname); //file(pathname) returns the content of the file.
console.log("Creating a response header")
response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"}); //Creating an answer header - we inform the browser that the body of the answer will be plain text
console.log("Creating the body of the response")
response.write('File content: '+ string); // Write content of the file
response.end(); //The end of the response - send it to the browser
console.log("Sending a response")
}
ALL CODE:
var http = require("http");
var url = require("url");
var fs = require('fs');
function file(pathname){
fs.stat(pathname, function(err, stats) {
console.log("----------------------------------------------------------");
console.log("FILE OPERATION RESULT:");
console.log("----------------------------------------------------------");
if (err){ console.log("'" + pathname + "' is not a directory or a file");
} else if(stats.isDirectory()){
console.log("Is a directory");
} else if(stats.isFile()){
console.log("Is a file");
console.log("Reading content...");
console.log("---------------");
fs.readFile(pathname, function (err, data) {
fileContent=data.toString('utf8');
console.log(fileContent);
return fileContent;
});
}
});
}
http.createServer(function(request, response) {
console.log("--------------------------------------")
console.log("The relative URL of the current request: "+request.url+"\n")
var url_parts = url.parse(request.url,true); //parsing (relative) URL
if(url_parts.pathname == '/submit') { //Processing the form content, if the relative URL is '/ submit'
var pathname=url_parts.query['name']; //Read the contents of the field (form) named 'name'
var string = file(pathname);
console.log("Creating a response header")
response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"}); //Creating an answer header - we inform the browser that the body of the answer will be plain text
console.log("Creating the body of the response")
response.write('File content: '+ string); //WRITE FILECONTENT IF PATHNAME IS A FILE
response.end(); //The end of the response - send it to the browser
console.log("Sending a response")
}
else { //Generating the form
console.log("Creating a response header")
response.writeHead(200, {"Content-Type": "text/html; charset=utf-8"}); //Creating a repsonse header - we inform the browser that the body of the response will be HTML text
//and now we put an HTML form in the body of the answer
console.log("Creating a response body")
response.write('<form method="GET" action="/submit">');
response.write('<label for="name">Write pathname</label>');
response.write('<input name="name">');
response.write('<br>');
response.write('<input type="submit">');
response.write('<input type="reset">');
response.write('</form>');
response.end(); //The end of the response - send it to the browser
console.log("Sending a response")
}
}).listen(8080);
console.log("The server was started on port 8080");
console.log("To end the server, press 'CTRL + C'");
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);
}
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.
I'm trying to use just straight vanilla Node.js with no frameworks other than what is necessary for educational purposes. I currently have this setup:
var fs = require('fs'),
jade = require('jade');
function compile(dirPath, res) {
var filePath = __dirname + dirPath;
fs.readFile(filePath, 'utf8', function(err, fd) {
var fn = jade.compile(fd, { filename: filePath, pretty: true});
res.write(fn());
res.end();
});
}
exports.compile = compile;
Which is called when the requested page is asked for, like this:
var jadec = require('./jadecompile');
function start(res, postData) {
res.writeHead(200, {"Content-Type": "text/html"});
var cpage = '/staticpages/index.jade',
page = jadec.compile(cpage, res);
}
The page loads great and I get this as my view source:
<!DOCTYPE html>
<html>
<head>
<title>Hello!</title>
<link rel="text/css" href="assets/css/bootstrap.css">
</head>
<body>
<div class="hero-unit">
<p>Hello This Is A Test</p>
</div>
</body>
</html>
But the css doesn't work at all, I've been trying to google it but every answer seems to use express or something else, but I want to learn how to do this as vanilla as possible, so my question is, how can I handle the *.css so that the css is loaded properly, when I click on the href link in the view source, it loads my 404 page, rather than just the plain text of the css file. Thanks!
Feel free to view the repo at: https://github.com/Gacnt/Node-Tests
I managed to fix my problem by creating a function to handle static pages, such as .css or .js, like so:
var http = require('http'),
url = require('url'),
path = require('path');
fs = require('fs');
// ADDED THIS FUNCTION HERE -----------------------------------------------------
function handleStaticPages(pathName, res) {
var ext = path.extname(pathName);
switch(ext) {
case '.css':
res.writeHead(200, {"Content-Type": "text/css"});
fs.readFile('./' + pathName, 'utf8', function(err, fd) {
res.end(fd);
});
console.log('Routed for Cascading Style Sheet '+ pathName +' Successfully\n');
break;
case '.js':
res.writeHead(200, {"Content-Type": "text/javascript"});
fs.readFile('./' + pathName, 'utf8', function(err, fd) {
res.end(fd);
});
console.log('Routed for Javascript '+ pathName +' Successfully\n');
break;
}
}
// ADDED THIS FUNCTION HERE -----------------------------------------------------
function start(route, handle) {
function onRequest(req, res) {
var postData = "",
pathName = url.parse(req.url).pathname;
console.log('Request for ' + pathName + ' received.');
req.addListener('data', function(data) {
postData += data;
console.log('Received POST data chunk ' + postData + '.');
});
req.addListener('end', function() {
var pathext = path.extname(pathName);
if (pathext === '.js' || pathext === '.css') {
handleStaticPages(pathName, res);
} else {
console.log('--> Routing only the view page');
route(handle, pathName, res, postData);
}
});
}
http.createServer(onRequest).listen(4000);
console.log('Server is now listening at: http://127.0.0.1:4000 .');
}
exports.start = start;
In order to handle .css and other static files, there needs to be a file stream in place. Rather than using a switch statement you can just use the following.
var stream = fs.createReadStream(path); //create the file stream
stream.pipe(res); //transfer the file