I am new to nodejs. I want to create a very simple website which has 3 pages. In every page I want to display an image to make the pages look uniform.
My code looks like this:
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var fs = require('fs');
var mail = require("nodemailer").mail;
/*List of variables*/
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.get('/main', function(req, res) {
fs.readFile('./home.html', function(error, content) {
if (error) {
res.writeHead(500);
res.end();
}
else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content, 'utf-8');
}
});
});
/* After this I have code for post event - all these navigation works perfectly fine*/
in home.html file I have an image to display:
/*Header part of HTML file*/
<body>
<img class="logo" src="./Heading.png" alt="My_Logo">
console.log (src);
<h1 class="center">Welcome to message reprocessing</h1>
</br>
</body>
This image is not displayed in my browser. When I check my console I have this error:
GET http://localhost:3000/Heading.png 404 (Not Found)
Please help, thanks
First, you have to set the public (folder) as static under server.js file
server.js
// configure our application
const Express = require('express');
const app = new Express();
.......
.......
app.use(Express.static(__dirname+'/public'));
.......
then your img source will be
<img class="logo" src="/images/Heading.png" alt="My_Logo">
and here the folders structure would be -
project(root folder) \ public \ images\ Heading.png
Thanks for your answers.I had tried using absolute path already with no luck. However one of my friend suggested as below:
<img class="logo" src="http://localhost:3000/images/Heading.png" alt="My_Logo">
and keep the Heading.png file in public/images directory.
Thanks all.
Okay, its not with express.js, but here is a snippet of my code that handles images and external javascripts, but has a protection:
function handler (req, res){
var pathname = url.parse(req.url).pathname;
var isImage = 0, contentType, fileToLoad;
var extension = pathname.split('.').pop();
var file = "." + pathname;
var dirs = pathname.split('/');
if(pathname == "/"){
file = "index.html";
contentType = 'text/html';
isImage = 2;
}
else if(dirs[1] != "hidden" && pathname != "/app.js"){
switch(extension){
case "jpg":
contentType = 'image/jpg';
isImage = 1;
break;
case "png":
contentType = 'image/png';
isImage = 1;
break;
case "js":
contentType = 'text/javascript';
isImage = 2;
break;
case "css":
contentType = 'text/css';
isImage = 2;
break;
case "html":
contentType = 'text/html';
isImage = 2;
break;
}
}
if(isImage == 1){
fileToLoad = fs.readFileSync(file);
res.writeHead(200, {'Content-Type': contentType });
res.end(fileToLoad, 'binary');
}
else if(isImage == 2){
fileToLoad = fs.readFileSync(file, "utf8");
res.writeHead(200, {'Content-Type': contentType });
res.write(fileToLoad);
res.end();
}
This assuming that you have your app.js and index.html in your root, you can have folders like /css, /img, /js etc. But the app.js and content inside your /hidden folder is unable to reach, but files in your root is still accessable.
If you want a quick solution, do this: instead of this <img class="logo" src="./Heading.png" alt="My_Logo"> use:
<img class="logo" src="your file path /Heading.png" alt="My_Logo">
Still not working?
check image spelling, file extension(png) because png and PNG are different in live server(case sensitive).
and verify
path.join(__dirname, 'public')
too
Index.js
Inside this file, add the code below to give the directory name to your index.js (server), in a way it is based on your actual directory path.
app.use(express.static(path.join(__dirname, "/public")));
Directory Structure
now inside Index.ejs (you HTML page) add the code below to insert your image and make it visible.
<div id="main-content">
<img src="img\navthome" />
</div>
Notice inside IMG tag we set the SRC as "img\navthome.gif", here we don't need to declare all the path since we already declared the __dirname, and the PUBLIC folder inside index.js
I hope it can helps you with your issue :D
One of the problems I had was that I wanted to define a few specific paths and I found the best answer in the link below.
https://www.geeksforgeeks.org/how-to-fetch-images-from-node-js-server/
// Requiring module
const express = require('express');
// Creating express object
const app = express();
// Defining port number
const PORT = 3000;
// Function to serve all static files
// inside public directory.
app.use(express.static('public'));
app.use('/images', express.static('images'));
// Server setup
app.listen(PORT, () => {
console.log(`Running server on PORT ${PORT}...`);
})
I did the following in my program:
Shows the structure of folders and files here
root
> client
> node_modules
> folder_1
> folder_2
> package.json
> server.js
And on my server I define that folder_1 in fl1 path and folder_2 in fl2 path each have a separate static path. And the interesting thing is that I do not use the original name of those folders and I give it my own route.
// Requiring module
const express = require('express');
const path = require('path');
// Creating express object
const app = express();
// http://localhost:3000/fl1/...
app.use('/fl1',express.static(path.resolve(__dirname,'folder_1')));
// http://localhost:3000/fl2/...
app.use('/fl2',express.static(path.resolve(__dirname,'folder_2')));
// Server setup
app.listen(3000, () => {
console.log(`Running server on port 3000`);
})
After running the server to access this path is enough to use the following path to access its contents.
Note that you must specify the internal routes accurately. For example, the subfolders and file name must be specified. main path /folder_1/img/image_1.png in url /fl1/img/image.png.
Related
I am trying to stream local video into web browser (chrome) and I used below code to stream local files
server.js
var walk = require('walk');
const app = express()
const port = 3000;
const ipaddr = "localhost";
app.use(express.static(path.join(__dirname, 'public')))
app.set('view engine', 'ejs');
const videoHomeDir = os.homedir() + `/Videos`;
var files = [];
var walker = walk.walk(videoHomeDir, { followLinks: false });
walker.on('file', function(root, stat, next) {
files.push(root + '/' + stat.name);
next();
});
walker.on('end', function() {
console.log("GOT ALL VIDEOS")
});
and code works file.
but problem was it display all file in the folder ( mp4 , txt , jpg ... ) but i expect only " Mp4 " files only.
How to display video files only on browser using node js local media streaming.
Maybe you can specify allowed extensions with walk?
otherwise you could only push the filename if the extension matches like:
if (stat.name.match('.mp4')) {
files.push(root + '/' + stat.name);
}
I'm getting ReferenceError: main is not defined
when I open up the http://localhost:3000/
Here I try to open up the main.html located in views directory
This is my app.js
const express = require('express'),
app = express(),
config = require('./config/index'),
routes = require('./routes/route');
app.use(express.static(`${__dirname}/public`));
app.use(express.static(`${__dirname}/views`));
app.use('/',routes);
app.listen(config.port,()=>{
console.log(`Listing at port ${config.port}`)})
This is my route.js
const express = require('express'),
router = express.Router(),
helpers = require('../helpers/index');
router.route('/')
.get(helpers.index)
module.exports = router
This is my helpers/index.js
var user = require('../user/user');
exports.index = (req,res)=>{
if(user.name == ''){
res.sendFile(main.html);
}
else{
res.sendFile(chat.html)
}
}
module.exports = exports;
Directory Structure
>helpers
>index.js
>routes
>route.js
>user
>user.js
>views
>main.html
>chat.html
app.js
pacakage.json
Change:
res.sendFile(main.html);
to:
res.sendFile("main.html");
Without the quotes, it's trying to interpret main as a Javascript object which it looks for the .html property on. But, there is apparently no object named main so you get ReferenceError: main is not defined. You want to pass a string here instead.
Same for res.sendFile("chat.html");
If the files are not local to this module's directory, then you need to build a more complete path that specifies their location. Given the file hierarchy you show, I think that might be something like this:
const path = require('path');
const options = {root: path.join(__dirname, "../views")};
res.sendFile("main.html", options);
var user = require('../user/user');
var path = require('path');
exports.index = (req,res)=>{
if(user.name == ''){
res.sendFile(path.resolve('views/main.html'));
}
else{
res.sendFile(path.resolve('views/chat.html'))
}
}
module.exports = exports;
In addition to jfriend00's answer, you must also, build the correct absolute path, using the global __dirname variable in node.
So your path will be something like: res.sendFile(__dirname + "/main.html")
or, depending on your folder structure: res.sendFile(__dirname + "/someadditionalfoldrs/main.html")
or, construct the path using "./" if applicable, like "./main.html";
I am using node.js to launch a serve so that my html can communicate with R code. But I am facing a problem on node.js. In my html page, I have a browse selection button, user can use it to choose the data file they want to read into html and node.js will pass the file name to R, so R code will read data from the selected data file and then run the analytics model. But as i only have very basic knowledge of Node.js, so currently, r code would run only when I open the followling link "localhost:3000/vis/rio". So my question is how to make node.js run the R code in background automatically when the data file has been selected. Thank you very much for your help in advance.
Here are my codes:
Javascript-(sending the file name to node.js):
var dataset,availableTags;
function handleFileSelect(evt) {
var file = evt.target.files[0];
$.ajax({ //getting the file name and update to node.js
type:'post',
url:"/getFileName",
data:{filename:file.name}
});
Papa.parse(file, { //papa is a library I used to read csv file
header: true,
dynamicTyping: true,
complete: function(results) {
dataset=results.data;
}
});
}
$(document).ready(function(){
$("#csv-file").change(handleFileSelect);
});
Node.js script:
serve.js:
var express=require('express');
var path = require('path');
var vis = require('./routes/vis');
var index = require('./routes/index');
var bodyParser=require('body-parser');
var app=express();
require('./routes/main')(app);
app.get('/vis/rio',vis.rio); **//this is a package used to get connection with Rserve**
app.set('views',__dirname + '/views');
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded());
app.post("/getFileName",index.getFileName); **//this is the script to get the file name, it is from index.js**
var server=app.listen(3000,function(){
console.log("Express is running on port 3000");
});
index.js // this is the js file for getting file name
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
getFileName=function (req,res){
global.filename=req.body.filename; **//this is the global variable which stores the file name**
res.send('true');
};
module.exports = {router:router,getFileName:getFileName};
vis.js // this is the file used to connect with Rserve and pass the name to R code
var rio = require("rio");
var arg={};
exports.rio = function(req, res){
arg={names:[global.filename]};
console.log(arg);
options = {
entryPoint:"nameoffile",
data: arg,
host : "127.0.0.1",
port : 6311,
callback: function (err, val) {
if (!err) {
console.log("RETURN:"+val);
return res.send({'success':true,'res':val});
} else {
console.log("ERROR:Rserve call failed")
return res.send({'success':false});
}
},
}
rio.enableDebug(true);
rio.sourceAndEval(__dirname + "/Rcode/test.R",options);
};
It looks like you aren't calling out to /vis/rio at any point when you make the call out to your server.
You'll either need to make a second call on the client side to /vis/rio or if you want to use that section, you can import/require the module in index.js and include it in getFileName and just call out to the function there before you return the file. I'm not super familiar with rio, but I don't see any access point in your code to that function.
Edit: If I understand what you're trying to do correctly, you can always make a second request (to /vis/rio) in the success callback of your first ajax call.
I cant get the contents included in the head of the served defualt.htm page to "work". The html loads in the dom, just the CSS and JS files fail. Is there a better alternative? Id like to keep the solution within NodeJS but alternatively open to socket.io and express as well.
Thanks, below is what im using.
NodeJS Serving the Page
var http = require('http'),
fs = require('fs');
fs.readFile(__dirname+'/default.htm', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(port.number);
});
Default.html Page
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="objects/css/site.css" type="text/css" />
<script src="objects/js/jquery.min.js" type="text/javascript"></script>
<script src="objects/js/site.min.js" type="text/javascript"></script>
</head>
<body></body>
</html>
Your Javascript and styles are failing because they don't exist. Your current webserver is only sending a single route, the root route. Instead you'll need to allow the use of multiple routes. ExpressJS does this for you in a simpler way, but still very possible without it.
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(request, response){
var header_type = "";
var data = "";
var get = function (uri, callback) {
// match `request.url` with uri with a regex or something.
var regex = uri;
if (request.url.match(regex)) {
callback();
}
};
var render = function (resource) {
// resource = name of resource (i.e. index, site.min, jquery.min)
fs.readFile( __dirname + "/" + resource, function(err, file) {
if (err) return false; // Do something with the error....
header_type = ""; // Do some checking to find out what header type you must send.
data = file;
}
};
get('/', function(req, res, next) {
// Send out the index.html
render('index.html');
next();
});
get('/javascript.min', function(req, res, next) {
render('javascript.js');
next();
});
});
server.listen(8080);
This might get you started, but you'll have to implement some things like next() yourself. A pretty simple solution, but a working one.
Another solution for responding to static files would be to create a catcher within the http.createServer callback. Within the get method, if the uris don't match, then you would look within a public folder matching the full uri to the file system structure.
I'm going to throw my two cents in here as well.
The way I solved the same problem with serving static files is that I started using the Paperboy module, which is deprecated in favor of the Send module nowadays.
Anyhoo, the way I solved it was to "hijack" the request before it went into my GET method and check the path of it.
The way I "hijack it" is as follows
self.preProcess(self, request, response);
and
preProcess: function onRequest(app, request, response){ //DO STUFF }
If the path contained the STATICFILES dir, I would do a diffrent serving of files otherwise I'd go with the "html"-path. Below is the //DO STUFF of the preProcess() function
var path = urllib.parse(request.url).pathname;
if(path.indexOf(settings.STATICFILES_DIR) != -1) {
path = settings.STATICFILES_DIR;
requestedFile = request.url.substring(request.url.lastIndexOf('/') + 1, request.url.length);
return resolver.resolveResourceOr404(requestedFile, request, response);
}
There might be a better way of doing this but this works like a charm for the things that I need it to do.
Using the Paperboy module I then, using the resolver.resolveResourceOr404(); function
deliver the file like so
resolveResourceOr404 : function (filename, httpRequest, httpResponse) {
var root = path.join(path.dirname(__filename), '');
paperboy.deliver(root, httpRequest, httpResponse)
.error(function(e){
this.raise500(httpResponse);
})
.otherwise(function(){
this.raise404(httpResponse);
});
}
Well, you are serving your default.htm file on all requests. So, when the browser asks for objects/js/jquery.min.js, your server returns the contents of default.htm.
You should really consider using express or some other framework.
what about trying this:
var http = require('http');
var fs = require('fs');
var path = require('path');
http.createServer(function (request, response) {
console.log('request starting...');
var filePath = '.' + request.url;
if (filePath == './')
filePath = './index.html';
var extname = path.extname(filePath);
var contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
case '.json':
contentType = 'application/json';
break;
case '.png':
contentType = 'image/png';
break;
case '.jpg':
contentType = 'image/jpg';
break;
case '.wav':
contentType = 'audio/wav';
break;
}
fs.readFile(filePath, function(error, content) {
if (error) {
if(error.code == 'ENOENT'){
fs.readFile('./404.html', function(error, content) {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
});
}
else {
response.writeHead(500);
response.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
response.end();
}
}
else {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
}
});
}).listen(8125);
console.log('Server running at http://127.0.0.1:8125/');
You're better off with using Express for this kind of stuff.
Something like this will do the job.
App.js
var express = require('express')
, http = require('http')
, path = require('path');
var app = express();
//Configure Your App and Static Stuff Like Scripts Css
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views'); // Your view folder
app.set('view engine', 'jade'); //Use jade as view template engine
// app.set("view options", {layout: false});
// app.engine('html', require('ejs').renderFile); //Use ejs as view template engine
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public')); //Use Stylus as the CSS template engine
app.use(express.static(path.join(__dirname, 'public'))); //This is the place for your static stuff
});
app.get('/',function(req,res){
res.render('index.jade',{
title:"Index Page
}
});
Index is a jade template page.Which renders into static html and works pretty good with express.
For a global static header to all of your pages you can make a template like this and include it in any.
static_header.jade
doctype 5
html
head
title= title
script(src='/javascripts/jquery-1.8.2.min.js')
block header
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content
And finally your index.jade which is using the static_header and own dynamic header with its own scripts.
extends static_header
block header
script(src='/javascripts/jquery-ui-1.9.1.custom.js')
script(src='http://jquery-ui.googlecode.com/svn/trunk/ui/i18n/jquery.ui.datepicker-tr.js')
link(rel='stylesheet',href='/stylesheets/jquery-ui-1.9.1.custom.min.css')
block content
h1= title
Put both of the files in your views folder and ready to roll.
I'm really a fan of the simplicity PHP offers in serving pages, everything is based on the filesystem. I want to do the same thing with Node. I tried one routing setup that worked like this for views, but broke my public folder:
//using express:
app.get('*', function(req, res) {
file = req.params[0].substr(1, req.params[0].length);
console.log('requesting: ' + file);
res.render(file, {locals: {
req: req,
params: req.query
}});
});
So...What's the best way to setup filesystem based/php style routing in Node?
I think that I build exactly what you are looking for. I use this to serve up .jade files, obviously you can tweak this for your use case.
var url = require('url');
var express = require('express');
var app = express.createServer();
var fs = require('fs');
app.set("view engine", "jade");
app.use(app.router);
app.use(express.static(__dirname + '/public'));
/**
* Generic "get" attempts to route to known JADE files.
* If no known JADE files, then we pass routing to next() (should be static).
*/
app.get('*', function(req, res, next) {
var pathname = url.parse(req.url).pathname.toLowerCase(); // make matching case insenstive
// First case: with no path name, render the default index.jade
if(!pathname) {
res.render('index', {});
}
// Second case: path ending in '/' points to a folder, use index.jade from that folder
else if (pathname === '/' || pathname.charAt(pathname.length-1) === '/' ){
res.render(__dirname + '/views' + pathname + 'index.jade', {});
}
// Third case: looks like an actual file, attempt to render
else {
// Attempt to find the referenced jade file and render that. Note 'views' is default path.
fs.stat( (__dirname + "/views" + pathname + '.jade'), function(err, stats){
// There was an error, the file does not exist pass control to the static handler
if(err || !stats) {
next();
}
// We found the file, render it.
else{
res.render(pathname.substring(1), {});
}
});
}
});
app.listen(port);
Note, there should be more app.use() statements there for handling cookies, parsing the body etc. Also, the second param of the render is always empty. You may want to fill this out with things like {layout: xyz} or generic variables that need to come in to the rendered pages.
You can use express.static()
For examples:
app.configure(function(){
app.use(express.static(__dirname + '/public'));
});
app.configure(function(){
app.use('/uploads', express.static(PATH_TO_UPLOAD_FOLDER));
});