Cannot rename the downloaded file - node.js

The Express version is 4.16.4
I downloaded a file :
... <i class="fa fa-download"></i>
router.get("/downloadfacturemaintenance/:facture", function (req, res) {
var facture = req.params.facture;
res.download(path.join(__dirname, '../config/uploads/facture_maintenance/'+facture), "facture.png", function (err) {
console.log(err);
});
});
At runtime the download starts. But the filename in the download is the filename in the first parameter of res.download ; although I defined an alternate name in the second parameter. But this second parameter is not considered ! So why ?
edit :
here is code :
router.post("/maintenancereparation", function (req, res) {
async.parallel({
types_vehicule: function (cb_types_vehicule) {
connexion.query("select type_vehicule_id, type_vehicule_lib from " + utils.getPrefixNomTables() + "type_vehicule order by type_vehicule_id", function (err, rows) {
if (err)
throw err;
cb_types_vehicule(null, rows);
});
},
maintenances: function (cb_maintenance) {
connexion.query("select m.maintenance_id, m.maintenance_date_fin, v.immatriculation, m.maintenance_terminee, m.maintenance_facture from " + utils.getPrefixNomTables() + "maintenance m join " + utils.getPrefixNomTables() + "vehicule v on m.vehicule_id = v.vehicule_id order by m.maintenance_terminee, m.maintenance_date_fin", function (err, rows) {
if (err)
throw err;
cb_maintenance(null, rows);
});
}
}, function (err, results) {
res.render("maintenancereparation", { "types_vehicule": results.types_vehicule, "maintenances_new": results.maintenances });
});
});
<!DOCTYPE html>
<html lang="fr">
<head>
<style>
.center {
text-align: center;
}
</style>
</head>
<body>
<form id="frm" style="margin-top: 10px;">
<fieldset>
<legend>Maintenance / Réparation</legend>
<div class="row form-group col-sm-12">
<div class="radio">
<label><input type="radio" name="type_action" id="action_maintenance" /> Maintenance</label>
</div>
<div class="radio">
<label><input type="radio" name="type_action" id="action_reparation" /> Demande de réparation</label>
</div>
</div>
<div id="div_maintenance">
<table class="table" id="list_maintenance">
<thead>
<tr>
<th>Véhicule</th>
<th>Date fin maintenance</th>
<th style="background: #FFDD00 !important; font-size: 13px !important;">Actions</th>
<th>Closed</th>
<th>facture</th>
</tr>
</thead>
<tbody>
<% maintenances_new.forEach(function(maintenance){ %>
<tr>
<td><%= maintenance.immatriculation %></td>
<td><%= maintenance.maintenance_date_fin %></td>
<td><%= maintenance.maintenance_id %></td>
<td><%= maintenance.maintenance_terminee %></td>
<td><%= maintenance.maintenance_facture %></td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<div id="div_repair">
<div class="row form-group col-sm-12">
<label class="col-sm-1">Type véhicule</label>
<select id="type_vehicule" name="type_vehicule">
<option value="">-- Sélectionner --</option>
<% types_vehicule.forEach(function(type_vehicule){ %>
<option value="<%= type_vehicule.type_vehicule_id %>"><%= type_vehicule.type_vehicule_lib %></option>
<% }) %>
</select>
</div>
</div>
</fieldset>
</form>
</body>
</html>
<script>
$(document).ready(function () {
$(":radio[name='type_action']").on("change", function () {
if ($("#action_maintenance").is(":checked")) {
$("#div_repair").hide();
$("#div_maintenance").show();
} else {
$("#div_maintenance").hide();
$("#div_repair").show();
}
});
$("#action_maintenance").prop("checked", true);
$(":radio[name='type_action']").change();
var list = $("#list_maintenance").DataTable({
"language": {
"loadingRecords": "Veuillez patienter...",
"processing": "Veuillez patienter...",
"zeroRecords": "Aucun résultat",
"emptyTable": "Aucun résultat"
},
"columns": [
{ "data": 0, className: "center" },
{ "data": 1, className: "center" }
],
"columnDefs": [
{
"targets": 1,
"render": function (data, type, row) {
return ( data == "" ? "" : (new Date(data)).toLocaleDateString() );
}
},
{
targets: [2],
orderable: false,
searchable: false,
render: function (data, type, row) {
if (row[3] == 1) {
var facture = row[4];
var fichier = facture.substring(facture.lastIndexOf("/") + 1);
var ext = fichier.substring(fichier.lastIndexOf("."));
//fichier = fichier.substring(0, fichier.indexOf("_"));
var url = "/track/vehicule/downloadfacturemaintenance/"+fichier;
return '<i class="fa fa-download"></i>';
}
else
return '<i class="fa fa-flag"></i>';
}
},
{
targets: [3,4],
orderable: false,
searchable: false,
visible:false
}
]
});
list.on("click", "a[data-id]", function () {
var pk = $(this).data("id"), vehicule = $(this).data("vehicule");
$("#george_content").load("/track/vehicule/clotureMaintenance/" + pk + "/" + vehicule);
});
});
</script>
router.get("/downloadfacturemaintenance/:facture", function (req, res) {
var facture = req.params.facture;
var fichier = facture.substring(facture.lastIndexOf("/") + 1);
var ext = fichier.substring(fichier.lastIndexOf("."));
fichier = fichier.substring(0, fichier.indexOf("_"));
res.download(path.join(__dirname, '../config/uploads/facture_maintenance/'+facture), "facture.png", function (err) {
console.log(err);
});
});

This code is working for me
app.get('/download', function(req, res){
const file = `${__dirname}/demo.jpg`;
//res.attachment()
res.download(file,"DEMO.jpg"); // Set disposition and send it.
});
If it's not working probably due to caching, clear browser cache, It should work then. I was also facing the same problem when I tried replicating the issue and it turned out there is nothing wrong with code. Then I opened a browser in incognito mode, it worked as expected.
Check response header Content-Disposition in both cases:
When you don't pass filename as the second arg to res.download:
Passing filename as the second argument:
Tested in

I tried replicating this problem with this code: https://github.com/alexkubica/stackoverflow-example-express-download-with-filename-parameter
I suspected at first that maybe it has something to do with you traversing up the directories but it worked just fine.
Is it possible for you to upload your code so we can debug it?
I'll try looking into it and update this answer once I come with a solution.

Related

How to work out with sending sms using nexmo in nodejs?

This is the route code:
router.get('/compose/:ID', function(req, res, next) {
var random = Math.floor((Math.random() * 1000000) + 1);
console.log("random = " + random);
res.render('compose', { random: random, Id:req.params.ID });
})
.post(function(req, res, next) {
var to = '917985754084';
var from = 'GrumpyText';
var text = req.body.OTP;
console.log(text);
nexmo.message.sendSms(from, to, text, function(err,success){
if(success)
console.log("SMS sent successfully!");
else {
console.log("error");
}
});
});
This is the handlebar code:
<main role="main" class="container">
<div class="jumbotron">
<h1>List of Contacts</h1>
<table class="table table-striped">
<thead>
<tr>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<form method="post" enctype="multipart/form-data">
<tr>
<td><input type="text" name="OTP" class="form-control" value="Hi. Your OTP is : {{random}}"></td>
<td></td>
</tr>
<tr>
<td><button type="submit" class="btn btn-lg btn-primary btn-block">Submit</button>
</td>
</tr>
</form>
</tbody>
</table>
</div>
</main>
Its coming to the route but the console is not printing the 'text'. aka console.log(text) means req.body.OTP is not printing anything. Earlier it was printing undefined.
Could you please rectify where it is stucking perhaps?
The issue you are hitting is body-parser doesn't handle multipart/form-data.
There are several options, but one of those is multer.
\* add these for multi-part*\
var multer = require('multer')
var upload = multer();
\* other code *\
router
.get('/compose/:ID', function (req, res, next) {
var random = Math.floor(Math.random() * 1000000 + 1);
console.log('random = ' + random);
res.render('compose', { random: random, Id: req.params.ID });
})
.post('/compose/:ID', upload.none(), function (req, res, next) {
var to = '917985754084';
var from = 'GrumpyText';
var text = req.body.OTP;
nexmo.message.sendSms(from, to, text, function (err, success) {
if (success) console.log('SMS sent successfully!');
else {
console.log('error');
}
});
});

I want to create a Search method that autodisplay some results

I'm creating a function that is looking for users in database.
I've done the server-side code, but I don't know how to display the results in the html code. I know that I have to write some JavaScript code but I don't know how
I found something on Google, but it doesn't work.
This is my route.
router.get('/search', isAuth, feedController.getSearch);
This is my controller.
exports.getSearch = (req,res,next) => {
const search = req.query.searchField;
User.find({
firstname:{
$regex: new RegExp(search)
},
}, {
_id:0,
__v:0
}, function (err,data) {
res.json(data);
}
).limit(10);
}
This is my HTML
<li>
<div class="search-box">
<form action="/search" method="GET" class="form-inline my-0 my-lg-0">
<input type="text" aria-label="Search" class="form-control mr-sm-0" onkeyup="showResults(this.value)" placeholder="Mirror-Mirror Search">
<span class="hightlight"></span>
<span class="bar"></span>
</input>
<button type="submit" class="search-btn"><i class="fas fa-search"></i></button>
</form>
</div>
<div style="position: relative; width:100%; top:-1px;">
<div class="border" id="search-results"></div>
</div>
</li>
And this is what I found on Google
var showResults = debounce(function(arg) {
var value = arg.trim();
if(value == "" || value.length <=0)
{
$("#search-results").fadeOut();
return;
}
else {
$("#search-results").fadeIn();
}
var jgxh = $.get('/controllers/feed/getSearch?searchField=' + value, function(data) {
$("#search-results").html("");
})
.done(function(data){
if(data.length === 0) {
$("#search-results").append('<p class="lead text-center mt-2">No results</p>');
} else {
data.forEach(x => {
$("#search-results").append('<a href="#> <p class="m-2 lead>' +x.firstname+' '+x.lastname + '</p></a>')
});
}
})
.fail(function(err){
console.log(err);
})
},200)
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this;
args = arguments;
var later = function () {
timeout = null;
if(!immediate) func.apply(context,args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if(callNow) func.apply(context,args);
};
};
I expected to autodisplay the results, but It doesn't work. I want to search in my database either for 'firstname' or 'lastname', I hope you can help me, thank you!

Html datalist option through JavaScript in node js

I want to pass data from MySQL database in datalist option. My application is written in express js using ejs view. I can't figure out how to pass database values to list in JavaScript and how to pass this list to ejs file.
add.js:
module.exports = {
addProductPage: (req, res) => {
let query = "SELECT shipper_names.Shipper_ID, shipper_names.Shipper_Name FROM shipper_names";
conn.query(query, (err, results) => {
if (err) {
return res.status(500).send(err);
}
res.render('add-product.ejs', {
title: "Add Product",
shipper_names: results[0],
message: ''
});
});
}
}
EJS file:
<!doctype html>
<html lang="en">
<div>
<a class="float-right" href="/" title="Home">Home</a>
</div>
<div class="contnainer">
<% if (message) {%>
<p class="text-container text-danger">
<%= message %>
</p>
<%}%>
<% if (shipper_names) {%>
<form class="add-player-form" action="" method="POST" enctype="multipart/form-data">
<div>
<input type="text" id="shippers_names" list="languageList" />
<!--your input textbox-->
<datalist id="languageList">
<option value=""> </option>
</datalist>
</div>
<button type="submit" class="btn">Add Product</button>
</form>
<% } else { %>
<p class="text center">Product Not Found. Go HereTo Add Product.</p>
<% } %>
</div>
</html>
module.exports = {
addProductPage: (req, res) => {
let query = "SELECT * from shipper_names"
conn.query(query, (err, results) => {
if (err) {
return res.status(500).send(err);
}
res.render('add-product.ejs', {
shipper_names: results
});
});
},
<div>
<input type="text" id="txtAutoComplete" list="names" />
<!--your input textbox-->
<datalist id="names">
<% shipper_names.forEach((shipper_names, index)=>{%>
<option id=<%= shipper_names.Shipper_ID%>>
<%= shipper_names.Shipper_Name%></option>
<%})%>
</datalist>
</div>
this is working

JSON value returning as 'undefined' despite being well formed in nodeJS and SQLite3

I am trying to do multiple async requests to a SQLite database and then render them in a web page using node/express and ejs templating. I am able to retrieve the data in JSON from the database request but when pushing it to another JSON object, it is returning as undefined.
app.js
//Set up web server
const express = require('express');
const app = express();
var dashboard = require('./dashboard.js');
var async = require('async');
//Set view engine and allow access to public/css
app.set('view engine', 'ejs');
app.use(express.static('public/css'));
//Start server
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
})
//Connect to database
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('fishtank.db');
//Home page
app.get('/', function(req, res) {
//Temps variables
var currentAmbientTemp = '18.2';
var lightStatus = 'OFF';
var airPumpStatus = 'OFF';
//Get temps from database
var tempHistoryQuery = "SELECT * FROM watertemp LIMIT 5";
var currentWaterTempQuery = "SELECT temp FROM watertemp LIMIT 1";
async.series({
tempHistory: function(callback){
db.all(tempHistoryQuery, (err, results)=> {
callback(results);
})
},
currentWaterTemp: function(callback){
db.all(currentWaterTempQuery, (err, results)=> {
callback(results);
})
}
},function(err, results) {
res.render('index', {
tempHistory: results['tempHistory'],
currentWaterTemp: results['currentWaterTemp'],
currentAmbientTemp: currentAmbientTemp,
lightStatus: lightStatus,
airPumpStatus: airPumpStatus
})
console.log(results);
});
});
index.ejs
<!-- views/pages/index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head><% include partials/head %></head>
<body class="container">
<!--HEADER-->
<header><% include partials/header %></header>
<!--MAIN BODY-->
<main>
<!--OVERVIEW SECTION-->
<div class="row">
<div class="col-md-12 dash-section">
<h3>Overview</h3>
</div>
<!--WATER TEMP-->
<div class="col-md-3 dash-panel">
<div class="panel panel-info">
<div class="panel-heading">WATER TEMP</div>
<div class="panel-body"><%= currentWaterTemp %>°C</div>
</div>
</div>
<!--AMBIENT TEMP-->
<div class="col-md-3 dash-panel">
<div class="panel panel-info">
<div class="panel-heading">AMBIENT TEMP</div>
<div class="panel-body"><%= currentAmbientTemp %>°C</div>
</div>
</div>
<!--LIGHT STATUS-->
<div class="col-md-3 dash-panel">
<div class="panel panel-info">
<div class="panel-heading">LIGHT STATUS</div>
<div class="panel-body"><%= lightStatus %></div>
</div>
</div>
<!--AIR PUMP STATUS-->
<div class="col-md-3 dash-panel">
<div class="panel panel-info">
<div class="panel-heading">AIR PUMP STATUS</div>
<div class="panel-body"><%= airPumpStatus %></div>
</div>
</div>
</div>
<!--DETAILS SECTION-->
<div class="row">
<div class="col-md-12 dash-section">
<h3>Details</h3>
</div>
<!--WATER TEMP DETAILS-->
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading"><strong>WATER TEMP HISTORY</strong></div>
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">Date/Time</th>
<th scope="col">Temp</th>
</tr>
</thead>
<tbody>
<% for(var i=0; i < tempHistory.length; i++) { %>
<tr>
<td><%= tempHistory[i].datetime %></td>
<td><%= tempHistory[i].temp %></td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
<!--AMBIENT TEMP DETAILS-->
<div class="col-md-4 ml-auto">
Ambient Temp Table
</div>
<!--TBC DETAILS-->
<div class="col-md-4 ml-auto">
TBC
</div>
</div> <!--End of row-->
</main>
<!--FOOTER-->
<footer><% include partials/footer %></footer>
</body>
</html>
console.log(results); is giving me:
{ tempHistory: undefined }
But when logging it from within the callback function, I get:
[ { id: 1, datetime: '2018-02-24 12:56:02.123456', temp: 29.5 },
{ id: 2, datetime: '2018-02-24 13:56:02.123456', temp: 28.5 },
{ id: 3, datetime: '2018-02-24 14:56:02.123456', temp: 26.5 },
{ id: 4, datetime: '2018-02-24 15:56:02.123456', temp: 26.7 },
{ id: 5, datetime: '2018-02-24 16:56:02.123456', temp: 25.9 } ]
Any help would be greatly appreciated.
EDIT
I suspect now that you are calling back in the wrong way. The first parameter of callback should be an error and the result should be the second parameter. See below:
async.series({
tempHistory: function (callback) {
db.all(tempHistoryQuery, (err, results)=> {
callback(err, results);
})
},
currentWaterTemp: function (callback) {
db.all(currentWaterTempQuery, (err, results) => {
callback(err, results);
})
}
},function (err, results) {
// Don't forget to check for error here.
});
Which can be simplified to:
async.series({
tempHistory: cb => db.all(tempHistoryQuery, cb),
currentWaterTemp: cb => db.all(currentWaterTempQuery, cb)
}, (err, results) => {
// ..
});
For reference see the example code of .series

how to display data after form submit using expressjs

**app.js** Code
app.get('/', function (req, res) {
res.render('index', {
data: docsData,
title: "EJS example",
header: "Some users"
});
});
app.post('/', function (req, res) {
var jname= req.body.firstname;
var lname= req.body.lastname;
var jemail= req.body.email;
var collection = dbConnect.collection('users');
var document={name:jname, lastname:lname, email:jemail};
collection.insert(document, {w: 1}, function(err, records){
console.log("Record added as "+records[0]._id);
});
dbConnect.collection("users").find({"name":jname}).toArray(function(err, docsData) {
console.log('checking error',err, docsData);
res.render('index', {
data: docsData,
title: "AJT Family",
header: "Some users"
});
});
});
**html code**
<div align="center" ng-controller="FormCtrl">
<form name="form" ng-submit="submitForm()" novalidate>
<table>
<tr><td>Name:</td>
<td>
<input id="firstname" type="text" ng-model="regform.firstname" name="firstname" required="" />
</td>
<td>
<div ng-show="form.$submitted || form.firstname.$touched">
<div ng-show="form.firstname.$error.required">Enter your name.</div>
</div>
</td>
</tr>
<tr>
<td>Last Name: </td>
<td>
<input id="lastname" name="lastname" type="text" ng-model="regform.lastname" required>
</td>
<td>
<div ng-show="form.$submitted || form.lastname.$touched">
<div ng-show="form.lastname.$error.required">Enter your Last name.</div>
</div>
</td>
</tr>
<tr>
<td>E-mail:</td>
<td><input id="email" type="email" ng-model="regform.email" name="uEmail" required="" /></td>
<td>
<div ng-show="form.$submitted || form.uEmail.$touched">
<span ng-show="form.uEmail.$error.required">Enter your email.</span>
<span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
</div>
</td>
</tr>
</table>
<input type="button" ng-click="reset(form)" value="Reset" />
<input type="submit" ng-disabled="!form.$valid" value="Save" />
<p id="hu"></p>
</form>
</div>
<%if(data) {%>
<h1>Users</h1>
<% data.forEach(function(user){ %>
<br>
<table>
<tr><td>Name: </td><td><%= user.name %> <%= user.lastname %></td></tr>
<tr><td>Email: </td><td><%= user.email %></td></tr>
</table>
<% }) %>
<% } %>
</body>
</html>
**javascript**
var result;
var app = angular.module('formExample', []);
app.controller('FormCtrl', function ($scope, $http) {
$scope.data = {};
$scope.submitForm = function() {
formData = $scope.regform;
console.log("posting data....");
var request = $http({ url: '/',data: $scope.regform, method: 'post' });
console.log(formData);
};
});
here I can save data on mongodb using expressjs. I need to display data after form submission. Here nothing is displaying after form submission. How to display that saved content in html using embedded Javascript.
What you'll want to do is change your res.render() call to do something like this:
res.render('index', {
data: docsData,
title: 'AJT Family',
header: 'Some Users',
body: req.body, // This is your form data as a JSON object.
});
Then, in your index template, you'll have access to your form data to display however you want, if you're using Jade, for instance, you might want to say like:
h1 Data!
p #{body}

Resources