How can I dynamically retrieve files from MySql / Node.js server? - javascript

I'm working on my CRUD app what I`m trying to do is to download files from MySql Nodejs server. Here the steps I've achieved so far:
I create the below function to query MySql database to find the id=179(just a random id). The function is inside a file called userContoller.js.
exports.readfile = (req, res) => {
connection.query('SELECT * FROM user WHERE id="179"', (err, rows) => {
if (!err) {
res.render('index', { rows, layout: 'main3' });
} else {
console.log(err);
}
console.log('The data from user table:\n', rows);
});
}
With Handlebars in another file called index.hbs I fetch the file with {{this.profile_image}}
{{#each rows}}
{{#if this.profile_image}}
<a href="{{this.profile_image}}" download>
<img class="card__image" src="{{this.profile_image}}" loading="lazy" alt="User Profile">
{{else}}
<img class="card__image" src="/img/cert.png" loading="lazy" alt="User Profile">
</a>
{{/if}}
In another file user.js I placed the router for the /index page.
router.get('/index', userController.readfile);
All work fine. What I want to do is to dynamically access the user id, instead of me inserting 'SELECT * FROM user WHERE id="179"'. To achieve this I create the following function exports.viewall(also included in userController.js). exports.viewall function download the correct name of the file but instead to download the *.jpeg version download a USELESS *.html version and same with other type of file like *.pdf.
exports.viewall = (req, res) => {
//User the connection
connection.query('SELECT * FROM user WHERE id=?', [req.params.id], (err, rows) => {
//when done with the connection, release it
if (!err) {
res.render('view-crew', { rows });
} else {
console.log(err);
}
// console.log('The data from user table:\n', rows);
});
}
How can I dynamically properly query the MySql/Nodejs server to download the file to my local machine?
for reference below I put the app.js:
const express = require("express");
const path = require('path');
const exphbs = require("express-handlebars");
const fileUpload = require('express-fileupload');
const mysql = require('mysql');
// to be removed when deployed in heroku
require("dotenv").config();
const cookieParser = require('cookie-parser');
// Parsing middleware
const app = express();
// default option
app.use(fileUpload());
//to load static file
app.use(express.static("public"));
app.use(express.static("upload"));
//Listen on port 5000
app.use(express.urlencoded({ extended: false })); //To parse URL-encoded bodies (as sent by HTML forms)
app.use(express.json()); //To parse the incoming requests with JSON bodies
app.use(cookieParser());
app.engine("hbs", exphbs({ extname: ".hbs" }));//Templating engine to change the extenion of file from .handlebar to .hbs
app.set("view engine", "hbs");
//link which tell to the server express.js to get the routeing from user.js
// const routes = require('./server/routes/user');
app.use("/", require('./routes/user'));
app.use('/auth', require('./routes/auth'));
// Connection Pool
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'nodejs-login'
});
app.post('', (req, res) => {
let sampleFile;
let uploadPath;
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
// name of the input is sampleFile
sampleFile = req.files.sampleFile;
uploadPath = __dirname + '/upload/' + sampleFile.name;
console.log(sampleFile);
// Use mv() to place file on the server
sampleFile.mv(uploadPath, function (err) {
if (err) return res.status(500).send(err);
connection.query('UPDATE user SET profile_image = ? WHERE id="179"', [sampleFile.name], (err, rows) => {
if (!err) {
res.redirect('/index');
} else {
console.log(err);
}
});
});
});
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Listening on port ${port}`));

You can use express dynamic routes. And pass a string variable for querying the sql database. like this
app.post('/:id', (req, res) =>{
const id = req.params.id.toString;
const queryString = `UPDATE user SET profile_image = ? WHERE id=${id}`
connection.query( queryString,
[sampleFile.name], (err, rows) => {
if (!err) {
res.redirect('/index');
} else {
console.log(err);
}
});
});

I re-think the whole problem and here is the solution working for me:
1- On my front-end side I simply add ../upload/ in front of my handlebar link to database as per below code:
DOWNLOAD
In this way I re-route the the link to the folder where I keep all the file on my server.
2- I modify the router, so dinamycally get the pic with the /:pic on client side request
router.get('/upload/:pic', function (req, res) {
var file = __dirname + '/../upload/' + req.params.pic;
res.download(file);
});
3- I left the controller as follow:
exports.viewall = (req, res) => {
connection.query('SELECT * FROM user WHERE id=?', [req.params.id], (err, rows) => {
if (!err) {
res.render('view-crew', { rows });
} else {
console.log(err);
}
// console.log('The data from user table:\n', rows);
});
}
In this way, I create a download point as per front end code which downloads any file from the server taking the name reference from the MySql database:)

Related

SQL data is not loading

Does anyone know why my request just gets stuck loading when trying to access my database ?
My database name is test. If set the database: books or something like that for example. Then it returns the error database is unknown: books so I assume that my password is correct it just isn't finding the test data base ?
// To import these packages remember to add "type":"module" to package Json
import express from "express";
import mysql from "mysql";
const app = express();
const db = mysql.createConnection({
host: "localhost",
user: "root",
password: "keks000207",
database: "test",
});
// This is an API request with an Express server
app.get("/", (req, res) => {
res.json("Hello this is the backend");
});
app.get("/books", (req, res) => {
const q = "SELECT * FROM books";
db.query(q, (err, data) => {
if (err) return res.json(err);
return data;
});
});
app.listen(8800, () => {
console.log("Connected to backend!");
});
Try db.connect() or similar method available in the file itself.
And Instead of return data inside the callback of db.query, you should use res.send(data), then you will get the response in the GET /books API.

How to set two root endpoints in one file Restful API with node.js & EXPRESS

I have root endpoint who work when users enter the url like this:
http://localhost:8000/?date=2019-10-20&station=41027&daysForward=3
I want to create second root endpoint in the same file with different query but that did not work.
My code:
// Create express app
var express = require("express")
var app = express()
var mysql = require('mysql')
var express = require("express")
var cors = require('cors')
app.use(cors())
// Server port
var HTTP_PORT = 8000
// Start server
app.listen(HTTP_PORT, () => {
console.log("Server running on port %PORT%".replace("%PORT%",HTTP_PORT))
});
var con = mysql.createConnection({
host: "192.168.1.1",
port: "3456",
user: "user",
password: "pass"
});
var con2 = mysql.createConnection({
host: "192.168.1.1",
port: "3456",
user: "user",
password: "pass"
});
let aladinModel= '';
let aladinModelStations = '';
app.route('/')
.get(function(req, res) {
// omitted
res.setHeader('Access-Control-Allow-Origin', '*');
const date = req.query.date;
const station = req.query.station;
const daysForward = req.query.daysForward;
try {
const query = `CALL aladin_surfex.Get_mod_cell_values_meteogram('${date}', ${station}, ${daysForward})`;
con.query(query, function (err, result, fields) {
if (err) throw err;
aladinModel = result;
});
res.json({aladinModel})
} catch(error){
console.log("Error query database!!!");
}
});
app.route('/stations')
.get(function(req, res) {
// omitted
res.setHeader('Access-Control-Allow-Origin', '*');
try {
const query2 = `SELECT Station,Ime FROM stations_cells`;
con2.query2(query2, function (err, result2, fields) {
if (err) throw err;
aladinModelStations = result2;
});
res.json({aladinModelStations})
} catch(error){
console.log("Error query database!!!");
}
});
app.use(function(req, res){
res.status(404);
});
I guess this is not the right way to route pages but I hope someone can explain to me with an example how I could fix the code - so when a user enters:
http://localhost:3000/stations
the data should be loaded.
I see this error when I try to open this link.
[nodemon] starting `node server.js localhost:8000`
Server running on port 8000
Error query database!!!
This query
SELECT station, ime
FROM stations_cells
on the second root point is fine. I try to SELECT with HeidiSQL and database return the data values ?
Where is the problem for the second root point ?
That might not be the case, but here's the suggestion (which doesn't fit in comment section)
app.route('/')
.get(function(req, res) {
// omitted
});
app.route('/stations')
.get(function(req, res) {
// omitted
});

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client in Node JS

I am trying to update a data using a specific ID which is not working but gives above error.
When I update, first I search the database for that specific id and then save the data to MongoDB
here is my server.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
//importing MongoDB model schema
let ToDo = require('./todo.model');
const app = express();
const todoRoutes = express.Router();
const PORT = 4000;
//middlewares
app.use(bodyParser.json());
app.use(cors());
app.use('/todos', todoRoutes);
//connection to the MongoDB database
mongoose.connect('mongodb://127.0.0.1:27017/todos', {useNewUrlParser: true});
const connection = mongoose.connection;
connection.once('open', () =>{
console.log("Connected to the MongoDB through port: 27017");
});
app.listen(PORT, () => {
console.log(`Listening to port: ${PORT}`);
});
//get all data - removed to show only the code snippet I am getting errors
//get data by an ID - removed to show only the code snippet I am getting errors
//add items to database -removed to show only the code snippet I am getting errors
//update items
todoRoutes.route('/update/:id').post((req, res) => {
let id = req.params.id;
ToDo.findById(id, (err, todo) => {
if(err) throw err;
if(!todo) res.status(400).send("No data found");
todo.todo_description = req.body.todo_description;
todo.todo_responsible = req.body.todo_responsible;
todo.todo_priority = req.body.todo_priority;
todo.todo_completed = req.body.todo_completed;
res.end();
todo.save().then(todo => {
res.json(200).send("Data Updated! " + todo);
res.end();
}).catch(err => {
res.status(400).send("Error occured! " + err);
});
});
});
This is the error I am getting...
Can someone please help me?
This error usually means that you send a response more than once.
Notice that you send two responses one after the other res.json() and res.end()
If you want for some reason to just end the response, use res.end(), otherwise use res.status(200).json({ result: ‘Data updated’ + todo })
If you send both, it will complain about trying to modify the response (via res.end()) after sending it (via res.status().json())
In the '/update/:id' route, you're sending a res.end() then doing it again 3 lines later. If you remove the first res.end(), it should work.
You should also return if todo is missing:
todoRoutes.route('/update/:id').post((req, res) => {
let id = req.params.id;
ToDo.findById(id, (err, todo) => {
if(err) throw err;
if(!todo) return res.status(400).send("No data found");
todo.todo_description = req.body.todo_description;
todo.todo_responsible = req.body.todo_responsible;
todo.todo_priority = req.body.todo_priority;
todo.todo_completed = req.body.todo_completed;
todo.save().then(todo => {
res.status(200).send("Data Updated! " + todo);
}).catch(err => {
res.status(400).send("Error occured! " + err);
});
});
});

Node.js delete record from SQLite database based on radio button selection

I have a simple node.js app which displays user login information stored in a SQLite database, with a radio button within each row. When the user selects a record and clicks the delete button, the appropriate record should be deleted.
The problem seems to be that I can't work out how to return the value of the selected radio button, they are all showing as 'undefined'. I have tried numerous different methods and am going around in circles. Help appreciated!
Edit: I think the issue is that I am using one GET method for everything, so the req.body is empty. Not sure how to fix it though!
var express = require('express');
var app = express();
var bodyParser = require("body-parser")
var path = require('path');
var sqlite3 = require("sqlite3").verbose();
// Open persistent file database "loginDB"
let db = new sqlite3.Database('./loginDB', sqlite3.OPEN_READWRITE, (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to the user database.');
});
// Route files in public
app.use(express.static('public'));
// Configure to use body-parser
app.use(bodyParser.urlencoded({extended: false}));
// Function to check if radio button is selected
function checkSelected(item) {
return item != "undefined";
}
// Function to identify ID of record selected for deletion
function getSelected(selections) {
var userID = selections.findIndex(checkSelected);
return userID;
}
// REST endpoint for displaying data
app.get("/delete", function(req, res, next) {
var radioArray = [];
// Query database to retrieve records
db.all(`SELECT * FROM UserLogin`, function(err, rows) {
if (err) {
console.error(err.message);
};
// Generate table with user data
res.write('<html><head>');
res.write('<meta charset="utf-8">');
res.write('<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">');
res.write('<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>');
res.write("</head><body>");
res.write("<h2> The User Information Table</h2><br>");
res.write("<table class = 'table table-bordered table-striped'><thead><tr>");
res.write("<strong><th> </th>");
res.write("<th>ID</th>");
res.write("<th>Username</th>");
res.write("<th>Password</th></strong></tr></thead><tbody>");
rows.forEach(function(row) {
res.write(`<tr><td><input type='radio' value='${row.ID}' id='optradio' name='optradio'></td><td>` +row.ID+ `</td><td>` +row.Username+ `</td><td>` +row.Password+ `</td></tr>`);
radioArray.push(req.body.optradio);
});
res.write("</tbody></table></body></html><br>");
res.write(`<button class="btn btn-default" type="submit" value="delete" class="btn btn-primary">Delete</button>`);
var whichRadio = getSelected(radioArray);
db.run(`DELETE FROM UserLogin WHERE ID = ?`, whichRadio, function(err) {
if (err) {
return console.error(err.message);
} console.log("Deleted ID " + whichRadio);
});
res.send();
});
});
app.listen(3000, function() {
console.log("Web server running at: http://localhost:3000");
console.log("Type Ctrl+C to shut down the web server");
});
I'm posting an answer to my question to help others with the same issue. Adding in form tags and setting up a separate POST method allowed me to get rid of the untidy code I was using to try and retrieve the radio button value, so the end result is neater.
var express = require('express');
var app = express();
var bodyParser = require("body-parser")
var path = require('path');
var sqlite3 = require("sqlite3").verbose();
// Open persistent file database "loginDB"
let db = new sqlite3.Database('./loginDB', sqlite3.OPEN_READWRITE, (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to the user database.');
});
db.serialize(function() {
db.run(`SELECT * FROM UserLogin`);
});
// Route files in public
app.use(express.static('public'));
// Configure to use body-parser
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
// REST endpoint for displaying data
app.get("/delete", function(req, res, next) {
// Query database to retrieve records
db.all(`SELECT * FROM UserLogin`, function(err, rows) {
if (err) {
console.error(err.message);
};
// Generate table with user data
res.write('<html><head>');
res.write('<meta charset="utf-8">');
res.write('<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">');
res.write('<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>');
res.write("</head><body>");
res.write("<h2> The User Information Table</h2><br>");
res.write(`<form id="deleteUserForm" action="/inputForm" method="POST"</form>`);
res.write("<table class='table table-bordered table-striped'><thead><tr><strong>");
res.write("<th> </th>");
res.write("<th>ID</th>");
res.write("<th>Username</th>");
res.write("<th>Password</th></strong></tr></thead><tbody>");
rows.forEach(function(row) {
res.write(`<tr><td><input type='radio' form="deleteUserForm" value='${row.ID}' id='optradio' name='optradio'></td><td>` +row.ID+ `</td><td>` +row.Username+ `</td><td>` +row.Password+ `</td></tr>`);
});
res.write("</tbody></table><br>");
res.write(`<button class="btn btn-default" type="submit" form="deleteUserForm" value="delete" class="btn btn-primary">Delete</button>`);
res.write(`</body></html>`);
res.send();
});
});
// REST endpoint for getting value of selected record ID and deleting the user
app.post('/inputForm', function(req, res) {
//res.send(req.body.optradio);
var userToDelete = req.body.optradio;
db.run(`DELETE FROM UserLogin WHERE ID = ?`, userToDelete, function(err) {
if (err) {
return console.error(err.message);
} res.redirect('/delete'); //Redirect to user information page
});
});
app.listen(3000, function() {
console.log("Web server running at: http://localhost:3000");
console.log("Type Ctrl+C to shut down the web server");
});

Why templates include file doesn't work

I'm learning how to use templatesjs from:
https://www.npmjs.com/package/templatesjs
They have an example of using include html file in other html file (using <%include%> tag)
When I'm trying to build my own example, it doesn't work (The screen is empty, with no errors):
var express = require('express');
var app = express();
var fs = require('fs');
var bodyParser = require('body-parser');
app.use(bodyParser.json())
var templatesjs = require('templatesjs');
// FILES
var MAIN_FILE = '/main.html';
/*
* Home page
*/
app.get('/', function (req, res) {
fs.readFile(__dirname + MAIN_FILE, function(err,data){
if(err) throw err;
templatesjs.set(data, function(err,data){
if(err) throw err;
res.send();
});
});
})
/*
* Startup
*/
var server = app.listen(8082, function () {
var host = server.address().address
var port = server.address().port
// start
console.log("App listening at http://%s:%s", host, port)
})
the main html.file looks:
<html>
<title> Tutorial -> Templates Js Server </title>
<head>
</head>
<body>
<div>
<%include Top.html%>
</div>
<div>
</div>
</body>
</html>
and Top.html file looks:
<p>TOP</p>
(I have tried to add <html> tag into Top.html, but same results);
The problem is that the web screen I'm getting is empty (with no errors at Node.js)
What am I doing wrong ?
It's because you doesn't send back any data to incoming request! your res.send() is empty. you should send something back if you really want to show it. for example: res.send('hello world').
If you want to render your template with your data, you could use templatesjs.renderAll() method to populate your html template with desired data as follows:
// set default directory for html partials
templatesjs.dir = "./public/partials/";
app.get('/', function(req, res) {
fs.readFile(__dirname + MAIN_FILE, function(err, data) {
if (err) throw err;
templatesjs.set(data, function(err, data) {
if (err) throw err;
var list = { // this is your data
name: 'your name'
};
templatesjs.renderAll(list, function(err, data) {
if (err) throw err;
res.send(data);
});
});
});
})
Top.html:
<p>Hello, my name is <%name%></p>
and this file should reside in ./public/partials/ directory as we set default include directory to this path;

Categories