I've been doing fine until I try to separate my code into routes, controllers and etc. Now I'm getting an error when I try to load the html file. When I go to the link http://localhost:3000/ I'm getting this error Error: ENOENT: no such file or directory, stat '/views/index.html'
This is my routes.js code
module.exports = function (app) {
var userController = require('../controllers/userController');
// app.use(require('express').static('../app/views/index.html'));
app.get('/', userController.renderHomePage);
app.post('/find', userController.getUser);
app.get('/get', userController.getUsers);
app.post('/add', userController.addUser);
}
And here's my userController.js file
var mongoose = require('mongoose');
var User = require('../models/user');
var express = require('express');
var app = express();
app.use(express.static('../app'));
exports.renderHomePage = function (req, res) {
res.sendFile('/views/index.html');
}
exports.addUser = function(req,res){
console.log(req.body);
var newUser = new User({
name : req.body.name,
username : req.body.username,
password : req.body.password
});
newUser.save(function(err){
if(err){
console.log(err);
}
else{
console.log("User Saved successfully");
}
});
res.send(req.body);
};
exports.getUsers = function (req, res) {
// body...
User.find({}, function(error, users){
if(error){
console.log(error);
}
else{
res.send(users);
}
})
};
exports.getUser = function (req, res) {
// body...
console.log(req.body);
var data = req.body.username;
User.find({username : data}, function(err, user){
if(err){
throw err
}
else{
console.log(user);
res.send(user);
}
} );
};
Here's my server.js
var express = require('express');
// var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var PORT = process.env.PORT || 3000;
var app = express();
var routes = require('./api/routes/routes');
routes(app);
var database = require('./config/database');
app.use(bodyParser.json());
app.listen(PORT, function(){
console.log("Server is running on port "+PORT);
})
And here's my folder structure.
Server starting without an error. And I thought I've given the paths correctly. But I'm getting the error. Can anyone help me with this ? Thanks.
EDIT :
This is how I've linked my script to the html file
<script src="/script/app.js"></script>
It's been two months, did you solve the problem ?
If not did you try that code :
app.use(express.static('app'));
The path you give to the static function is relative to the directory where you run your node process.
In your case, you start your server with/from the server.js file (at the root directory), so the path you give to the static function is relative to this location.
A path starting with / is an absolute path, meaning it resolves based on the root directory (on Windows, something like C:\, on linux it's just /).
You should be using the path module to get paths to files relative to the module's directory like so:
var path = require('path');
var filePath = path.join(__dirname, 'relative/path/to/file');
__dirname is a special module-scoped variable that provides the path to the current module's containing directory.
app.use(express.static('../../app'))
Try adding another '..' in your userController.js file, just one .. will put you at the api directory.
Include the 'path' module and change
res.sendFile('/views/index.html');
to
res.sendFile(path.resolve(`${__dirname}/views/index.html`))
I ran into this problem. You are sending the html file with res.send, but your scripts are not in a directory that can be reached by your statically available files.
Just saw your EDIT. With your EDIT you are closing in on it. Change the reference in your HTML file of your script include.
Related
Good morning. I'm developing a portfolio app with projects. I did a mongoDB database and a NodeJS and express conexion to this database. I'm doing a controller with a method that allows me to upload a image to the database. I did this method, but when I use it with PostMan, the image is uploaded to the folder I indicate, but the files arguments don't appear and I need then to upload to the database.
I upload the code
Controller
uploadImage: function(req, res){
var projectId = req.params.id;
var fileName = "Imagen no subida...";
if(req.files){
return res.status(200).send({
files: req.files
});
}else{
return res.status(200).send({
message: fileName
});
}
}
Routes
'use strict'
var express = require('express');
var ProjectController = require('../controllers/project');
var router = express.Router();
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart({ uploadDir: './uploads' });
router.get('/home', ProjectController.home);
router.post('/test', ProjectController.test);
router.post('/save-project', ProjectController.saveProject);
router.get('/project/:id', ProjectController.getProject);
router.get('/projects', ProjectController.getProjects);
router.put('/project/:id', ProjectController.updateProject);
router.delete('/project/:id', ProjectController.deleteProject);
router.post('/upload-image/:id', multipartMiddleware ,ProjectController.uploadImage);
module.exports = router;
app.js
'use strict'
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
// cargar archivo Rutas
var routes = require('./routes/project');
// Middlewares
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
// CORS
// Rutas
app.use('/api', routes);
// exportar
module.exports = app;
PostMan
I use form-data and I add an image.
Response:
{
"files": {}
}
I think in files JSON there are differents params to upload image to the dataBase, like filePath, fileName...
Thanks in advance
I think it should be req.files.file not req.files
If req.files.file does not exist, try to console.log(req), and console.log(req.files) to trace the file
Update
check that the Content-Type in the headers sections in postman is "multipart/form-data"
then you can find your file in req.files.image, as you name it image in form-data body section
hope it helps
thank you for your answer.
I did the two things, but when I do the console.log(req.files) the response is {}, and when I do console.log(req.files.file) the response is undefined.
I don't know what happens, I'm using a .jpg extension image.
Again thank you
thank you.
I send you an image of the PostMan request. I send you in i.stack because is the only way I can send the image.
[![[1]: https://i.stack.imgur.com/NHDog.png][1]][1]
The code:
// Multer
const storage = multer.diskStorage({
destination: function(req, res, cb){
cb(null, './uploads')
},
filename: function(req, file, cb){
cb(null, file.fieldname + "-" + Date.now())
}
})
const upload = multer({ storage: storage });
The function:
uploadImage: function(req, res, next){
console.log(req.file);
}
The request:
router.post('/upload-image/:id', upload.single('image'), ProjectController.uploadImage);
I trying to write a NodeJS project that read JSON files from the project directory and response back the JSON file data whenever, user trigger a specific URL.
For the Project below, I am able to get the JSON data response when I trigger http://localhost:8081/api/user in web browser.
In order to make this work I have to explicitly hardcode a function that response to a specific URL. For example, if I wanted to add 1 more JSON files in the api folder and enable user to access it, I have to explicitly hardcode another function just to response to different request.
app.get('/api/newJSONFile', (req, res) => {
fs.readFile( __dirname +'/api/newJSONFile' +".json", 'utf8', function (err, data) {
res.send(data);
res.end( data );
});
});
So, after adding the code above the user will able to access the JSON file through http://localhost:8081/api/newJsonFile. Without the explicitly hardcode
function above user will not able to get response when launch the http://localhost:8081/api/newJsonFile
My Question:
Is this the only way to perform the response upon URL request? It seem inefficient, as if I have 100 JSON File then I have to explicitly hardcode another 100 functions.
What is the proper way to code the implementation?
Thank you.
My Project Structure:
server.js
const express = require('express');
const app = express();
const fs = require("fs");
app.get('/api/user', (req, res) => {
fs.readFile( __dirname +'/api/user' +".json", 'utf8', function (err, data) {
res.send(data);
res.end( data );
});
});
var server = app.listen(8081, () => {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
You can use the express static middleware to serve static json files from a specified folder.
const express = require('express');
const app = express();
// Setup express static middleware to look for files in the api directory for all requests starting with /api
app.use('/api', express.static('api') , function(req, res){
// Optional 404 handler
res.status(404);
res.json({error:{code:404}})
});
var server = app.listen(8081, () => {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
You can then access your user.json in the folder /api/user.json at localhost:8081/api/user.json
EDIT:
If you want to be able to add multiple folders, you can create a designated public (you can call it anything, actually) directory and put all your top level folders there.
Consider the following JSON files stored in a nested fashion:
/public/api/user.json [ One level nest in api folder]
/public/data/config.json [ One level nest in data folder]
/public/data/server/config.json [Two level nest in data -> server folder]
you can then do
const express = require('express');
const app = express();
// EDIT: added options to ensure json can be accessed without extension
app.use(express.static('public',{index:false, extensions:['json']}));
app.use(function (req, res) {
// Optional 404 handler
res.status(404);
res.json({
error: {
code: 404
}
});
})
var server = app.listen(8081, () => {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
and then access your files as :
localhost:8081/api/user.json OR localhost:8081/api/user
localhost:8081/data/config.json OR localhost:8081/data/config
localhost:8081/data/server/config.json OR localhost:8081/data/server/config
Reference for options accepted by the express static middleware
Additional Improvement
NOTE: This method may accidentally expose sensitive server side configuration files [like your package.json] and potentially your entire codebase. Please use this method carefully and only if you know what you are doing.
If you do not want to create a designated directory (in this case 'public' folder) and put all your top level folders there in order to access it, you can use the code below to dynamically serve your files:
const express = require('express');
const app = express();
var publicdir = __dirname + '/';
app.use(express.static(publicdir,{extensions:['json']})); //or ,{index:false, extensions:['json']}
app.use(function (req, res) {
res.status(404);
res.json({
error: {
code: 404
}
});
})
var server = app.listen(8081, () => {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
You could expect file name in the url and then use just one route handler to deliver JSON files.
app.get('/api/:jsonFile', (req, res) => {
fs.readFile( __dirname +'/api/' + req.params.jsonFile +".json", 'utf8', function (err, data) {
res.send(data);
res.end( data );
});
});
Do add proper error handling like if file does not exists, then send back 404 using something like below:
if (!fs.existsSync(path)) {
res.status(404).send("");
}
Edit:
To return pretty JSON object try using the following:
res.header("Content-Type",'application/json');
res.send(JSON.stringify(YOUR_JSON_OBJECT, null, 4));
Express supports parameters in your route.
So having an arbitrary string from the url is as easy as modifying your route to :
app.get('/api/:file', (req, res) => {
fs.readFile( __dirname +'/api/' + req.params.file + ".json", 'utf8', function (err, data) {
res.send(data);
res.end( data );
});
});
I know there are lots of questions similar to mine but I could not find the best solution.
I am creating a web app with node and rethinkdb. I want to organise different js files (modules) so that each has specific task.
I have this query.js file whose query result must be passed to routes.js file.
I have tried implement this in the following way.
query.js
//dependencies
var express = require('express');
var path = require('path');
var r = require('rethinkdbdash')({
port: 28015,
host: 'localhost',
db: 'stocks'
});
var len;
//function to get companies list
exports.clist = function(){
r.table('company')
.run()
.then(function(response){
return response;
})
.error(function(err){
console.log(err);
})
}
console.log(exports.clist[0].id)
//function to get number of entries in database
exports.clen = function(){
r.table('company')
.run()
.then(function(response){
len = Object.keys(clist).length;
return len;
})
.error(function(err){
console.log(err);
})
}
routes.js
//dependencies
var express = require('express');
var request = require('request');
var path = require('path');
var r = require('rethinkdbdash')({
port: 28015,
host: 'localhost',
db: 'stocks'
});
//query module
var query = require('./query')
clist = query.clist();
clen = query.clen();
//create router object
var router = express.Router();
//export router
module.exports = router;
//home page
router.get('/', function(req, res) {
console.log('served homepage');
res.render('pages/home');
});
//--companies page--//
router.get('/company', function(req,res){
console.log('served companies page')
res.render('pages/company', {
clist: clist,
x:clen
});
});
the console log in query.js is showing that cannot read property id of undefined.
Also I would like to know is there a way to directly pass the variables instead of using functions and then calling it.
I apologise if the solution is obvious.
To summarise I want the query result which is an object to be accessible from routes.js file.
Note: As exports.clist1 is an asynchronous method, you can't expect the result to be printed in the next line, hence comment this line and follow as below
//console.log(exports.clist[0].id)
You have to register a middleware to make this working, otherwise, query will be called only at the time of express server started and not at every request.
So you can do like this,
Hope you had something like this in your startup file (app.js),
var app = module.exports = express();
routes.js
//query module
var query = require('./query')
var app = require('../app'); // this should resolve to your app.js file said above
//clist = query.clist();
//clen = query.clen();
// middleware to populate clist & clen
app.use(function(req, res, next){
query.companyList(function(err, data){
if(!err) {
req.clist = data.clist;
req.clen= data.clen;
}
next();
});
});
query.companyList(function(err, data){
if(err) {
console.log(err);
} else {
console.log(data.clist[0].id);
console.dir(data.clist);
}
});
//create router object
var router = express.Router();
//export router
module.exports = router;
//home page
router.get('/', function(req, res) {
console.log('served homepage');
res.render('pages/home');
});
//--companies page--//
router.get('/company', function(req,res){
console.log('served companies page')
res.render('pages/company', {
clist: req.clist,
x: req.clen
});
});
Change your query.js like this,
//function to get companies list
exports.companyList = function(next){
r.table('company')
.run()
.then(function(response){
var list = {
clist: response,
clen: Object.keys(response).length
};
next(null, list);
})
.error(function(err){
console.log(err);
next(err);
})
};
var express = require('express'),
app = express(),
db = require('./db'),
bodyParser = require('body-parser'),
controller = require('./controller');
app.use(express.static('../public'));
app.get('/server', function (req, res) {
console.log(__dirname);
res.sendFile('/../client/index.html');
});
I have this express server set up but using the code above I get "Cannot GET /" when I view localhost:portnumber. If I change the GET method to:
app.get('/', function(req, res) {
res.sendFile(__dirname + '../client/index.html');
});
I get "'C:\Users\TC\Documents\Desktop\myapp\multiplayerWebSite\server..\client\index.html' at Error (native)" and if I change it to:
app.get('/', function(req, res) {
res.sendFile('../client/index.html');
});
I get "TypeError: path must be absolute or specify root to res.sendFile"
Error: ENOENT: no such file or directory
The server was working perfectly when I had everything in the root directory, but I wanted to change the folder structure to make it more neat/professional. If anyone could tell me what I'm doing wrong I'd appreciate it greatly. Thank you in advance!
You can use path module, there is a join method that take multiple paths to make one.
Exemple if you do:
path.join('test/musicfolder', '../videofolder/allreadyseen')
you will get 'test/videofolder/allreadyseen' .
you can see all the doc here : https://nodejs.org/api/path.html
var express = require('express'),
path = require('path'),
app = express(),
db = require('./db'),
bodyParser = require('body-parser'),
controller = require('./controller');
app.use(express.static(path.join(__dirname, '../public')));
app.get('/server', function (req, res) {
console.log(__dirname);
res.sendFile(path.join(__dirname, '../client/index.html'));
});
I'm just now started to learn Node and Express, I have some probelm with the routes in express. I want a well modular code for routing. I want to query some data from mysql database:
Here is my app.js(it is on "public_html" directory):
var path = require('path');
var express = require('express');
var routes = require('./routes');
var app = express();
var staticPath = path.resolve(__dirname, './');
app.use(express.static(staticPath));
routes.init(app);
module.exports = app;
app.listen(3000, function() {
console.log('Server is listening on port: 3000');
});
Next file: "public_html/routes/index.js":
exports.init = function(app){
//electronics routes
app.use('/laptop', require('./laptop'));
};
"public_html/routes/laptop/index.js":
var router = require('express').Router();
router.get('/laptop', require('./modules/laptop'));
module.exports = router;
"public_html/routes/laptop/modules/laptop.js":
var mysql = require('mysql');
var connection = mysql.createConnection(
{
host : 'localhost',
user : 'admin',
password : 'xxxxxxx',
database : 'database',
}
);
module.exports = function(req, res){
connection.connect();
var queryString = 'SELECT * FROM laptop';
connection.query(queryString, function(err, rows, fields) {
if (err) throw err;
res.writeHead(200, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(rows));
});
connection.end();
};
I want to keep this modularity even if its look like a bit over complicated, in the future I will need it.
So the problem is it's just doesn't working, I think its just a stupid error somewhere, but I don't find it and on the internet there is only simple route examples so I cant use them in this case.
The problem is most likely in your routing.
You're mounting a separate router at /laptop. Within that mounted router you're setting up a /laptop (GET) route on top of that, so the full path would be /laptop/laptop.