trouble using fs module to locate file - node.js

Here is my code:
connection.query("SELECT * FROM images", function(err, rows, fields) {
if (err) {
console.log("Error: ");
console.log(err);
}
else {
console.log("rows: ");
console.log(rows);
for (var i = 0; i < rows.length; i++) {
var thisRow = rows[i];
var thisImageName = thisRow["imagename"];
var newDir = __dirname.split(path.sep).join("/");
var thisImagePath = newDir + "/public/uploads/" + thisImageName + ".jpg";
console.log(thisImagePath);
fs.exists(thisImagePath, function(exists) {
if (exists) {
console.log("true");
res.end();
}
else {
console.log(thisImageName + " does not exist."); res.end();
//Always returns false
}
});
}
}
});
HOWEVER,
In the console:
fs.exists(/* imagepath */, function(exists){console.log(exists)}) //returns true
As you can see I'm using the node-mysql library to return the file names of my images. I concatenate them using the __dirname global and then I reverse the slashes in the directory string to use in the .exists() call. When I use the fs module to check if the image file exists, it returns false.
HOWEVER, if I use fs.exists() with the same path in the console, it returns true. Does anyone know what's going on here?

Related

How to make while loop with switch case synchrounous in nodejs?

How can I make the while loop with switch-case synchronous in nodejs? Below is the code I am trying to iterate for 2 iterations of the while loop. But the problem is the next iteration gets iterated even before completing all the synchronous functions here which are readdirSync, readFileSync, etc.
What I want is with each whileloop iteration it should run all the methods and then again for next iteration.
Currently the output is:
i = 0
i = 1
Below is my code:
const dir4Data = 'C:/Users/em/Desktop/Regex_test_case/data/google_forms';
const dir4Polls = 'C:/Users/em/Desktop/Regex_test_case/Poll_Report';
var dir, i=0;
var regex4Data = /^\d{1,2}([./-])\d{1,2}\1\d{4}$/;
var regex4Polls = /^[1-9]\d*$/;
while(i < 2)
{
switch (i) {
case 0:
dir = dir4Data;
break;
case 1:
dir = dir4Polls;
break;
}
console.log('i = ', i);
fs.readdirSync(dir, function(err,files){ //Get a listing of all the files in the dir
if (err) throw err;
files.forEach(function(file){
//console.log("file = "+ file);
const writePath = 'C:/Users/em/Desktop/Regex_test_case/output/'+file;
fs.readFileSync(dir+'/'+file, function(err, data) {
console.log("data = "+ data);
var csvContent = data.toString().split('\n'); // read file and convert to array by line break
csvContent.forEach((item, index) => {
var csv;
if(!regex4Data.test(item.toString().split(' ')[0]) && index != 0 && i == 0) {
csv = csvContent[index-1].replace(/(\r\n|\n|\r)/gm, ""); // remove the breaks
// console.log(index, ' Replaced', csv);
fs.appendFileSync(writePath, csvContent[index].toString()+ ' ', function (err, data) {
if (err) throw err;
//console.log('Saved!');
})
}
else if(!regex4Polls.test(item.toString().split(',')[0]) && index != 0 && i == 1) {
csv = csvContent[index-1].replace(/(\r\n|\n|\r)/gm, ""); // remove the breaks
// console.log(index, ' Replaced', csv);
fs.appendFileSync(writePath, csvContent[index].toString()+ ' ', function (err, data) {
if (err) throw err;
//console.log('Saved!');
})
}
else {
csv = item.toString();
fs.appendFileSync(writePath, "\n"+csv + " ", function (err, data) {
if (err) throw err;
//console.log('Saved!');
})
}
});
})
})
})
i++;
}
There are two main error in your script.
First of all, you are using wrong the FS module function.
From the doc, https://nodejs.org/api/fs.html#fs_synchronous_example, all the FS Sync function are synchronous. That means that you don't have to pass them a callback.
You can just write
var response = fs.readFileSync(path);
And the value of response is your file.
The other thing is, if you wont to iterate an async function, you cannot with callback, but you can do it using async/await.
Here an example of loop working:
async function loop() {
var i = 0
while (i < 2) {
var response = await fs.promises.readFile(path);
console.log(response)
i++
}
}

Read files from folders inside a folder

So basically I have a folder, which holds other folders and each folder has it's own set of images, that I would like to display in a 'ul'. The problem is since I'm using readdir, which is async, how can I write the response, without getting a "Write after .end() error". Here is how my code looks like.
var fs = require('fs'),
url = require('url');
module.exports = function(req, res) {
req.pathName = req.pathName || url.parse(req.url).pathname;
if(req.pathName === '/gallery') {
fs.readdir('./content/images/public', function(err, filenames) {
if (err) {
console.log(err);
return;
}
if(filenames.length) {
var list_content = '';
for (var i = 0; i < filenames.length; i++) {
fs.readdir('./content/images/public/' + filenames[i], function(err, images) {
if (err) {
console.log(err);
return;
}
for (var i = 0; i < images.length; i++) {
list_content += '<li>' + images[i] + '</li>';
}
var list = '<ul>' + list_content + '</ul>Go back to homepage';
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.send(list);
});
}
} else {
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.write('<p>There are no images in the gallery</p>Go back to homepage');
res.end();
}
});
} else {
return true;
}
}
res.end();
}
});
Instead of using res.write() and res.end(), try using res.send(), which does both for you. UPDATE: Also, make sure this code is within a request callback where req, and res object is parsed correctly.
for (var i = 0; i < images.length; i++) {
list_content += '<li>' + images[i] + '</li>';
}
var list = '<ul>' + list_content + '</ul>Go back to homepage';
res.send(list);
then on the front end, receive it in the ajax response callback, like
$.post('xxxx', function(response){
alert(response); //list
});
UPDATE: after seeing your updated code,
module.exports = function(req, res) {
doesnt make sense, it needs to be something like
exports.functionName = function(req,res){
read this
https://www.sitepoint.com/understanding-module-exports-exports-node-js/
module.exports is an object of functions. Not a function. It looks like this
module.exports = {
funcExample: function() {
return 2;
},
funcOtherExample: function() {
return 1;
}

local variable is not changing

I'm using node.js for converting text files to CSV. It works for one file, but when i try process more files fileDestination variable doesn't change. Why? Input files like this: r10_1C_BP1-11_e41-81_10_5X1x9_05_train2.res
I got following console output:
./1_train.csv has been written successufully! r10_1C_BP1-11_e41-81_10_5X1x9_05_train2.res
./1_train.csv has been written successufully! r10_1C_BP1-11_e41-81_1_5X1x9_05_train2.res
/*
* lee archivos *.dat y los convierte *.csv
*/
const fs = require('fs');
const inputDir = './';
const outputDir = './';
function readFiles(inputDir, onError) {
fs.readdir(inputDir, function(err, filenames) {
if (err) {
onError(err);
return;
}
filenames.forEach(function(inputFile) {
// first we arre looking for "right" file name
if (inputFile.search(/res/) != -1) {
console.log('Starting processing ' + inputFile);
convert2csv(inputFile, function(error) {
throw err;
});
}
});
});
}
function convert2csv(filename, onError) {
arrayFromFilename = filename.split('_');
epoca = arrayFromFilename[4];
trainORval = arrayFromFilename[7].replace('2.res', '');
console.log("from convert " + filename + " " + epoca);
fs.readFile(inputDir + filename, 'utf-8', function(err, content) {
if (err) {
onError(err);
return;
}
content = content.replace(/^[^0].*\n/mg, '');
arr = content.split('\n');
pares = arr.filter(function(d, i) {
return i % 2 == 1;
});
content = pares.join('\n');
content = content.replace(/(^[\d.]*) ([\d.]*)/gm, '$1,$2');
fileDestination = outputDir + epoca + '_' + trainORval + '.csv';
console.log("filedestination :" + fileDestination);
fs.writeFile(fileDestination, 'y,x\n', function(err) {
if (err) {
return console.error(err);
}
fs.appendFile(fileDestination, content, function(err) {
if (err) {
return console.error(err);
}
console.log(fileDestination + " has been written successufully!", filename);
});
});
});
}

Node js - Wierd variable scope

Here's the code I use to browse a directory :
var path = 'D:/Syslog/live';
listDir(path);
function listDir (path) {
fs.readdir(path, function(err, files)
{
console.log(files);
for( i = 0; i < files.length; i++)
{
var fullPath = path + "/" + files[i];
fs.stat(fullPath, function(err, stats){
if (stats.isDirectory())
{
listDir(fullPath);
} else
{
console.log(files[i]);
}
});
}
});
}
When I debug and use the variable fullPath it works fine, if I use files[i] (which is declared in the level, i is undefined
As it's an asynchronous loop, i is iterating much faster than the rest of the code. You can use an anonymous closure function to freeze i within the loop.
Have a look at closures.
The popular async library is good for this sort of stuff too.
function listDir(path) {
fs.readdir(path, function(err, files) {
console.log(files);
for (i = 0; i < files.length; i++) {
(function(i) {
var fullPath = path + "/" + files[i];
fs.stat(fullPath, function(err, stats) {
if (stats.isDirectory()) {
listDir(fullPath);
} else {
console.log(files[i]);
}
});
})(i);
}
});
}
If you were using the async library, it'd look similar to this
var async = require('async');
function listDir(path) {
fs.readdir(path, function(err, files) {
console.log(files);
async.each(files, function(file, callback) {
var fullPath = path + "/" + file;
fs.stat(fullPath, function(err, stats) {
if (stats.isDirectory()) {
listDir(fullPath);
} else {
console.log(file);
}
callback();
});
});
});
}
Both tested and working.

node.js move bunch of files

i have made a form for file upload and i have set the multiple option, so im trying to upload a bunch of files and then move them according to the album name that the client have set,
here is what iv done:
if (req.body && req.body.album){
var album_name = req.body.album;
}
else{
//need to change to time instead of random album
var album_name = 'unknown_album-' + (parseInt(Math.random() * 5) + 1);
}
//File name
var file_name = null;
switch(req.files.img_file.type){
case 'image/png':
file_name = new Date().getTime() + '.png';
break;
case 'image/jpeg':
file_name = new Date().getTime() + '.jpeg';
break;
default:
res.render('admin/panel', {
title: 'אדמין',
message: 'קובץ לא תקין'
});
break;
}
mkdirp('./public/img/albums/' + album_name, function (err) {
if (err)
console.error(err);
else
{
_.each(req.files.img_file,function(val,index){
console.log(val.path + " " + index);
//gives the file path so i can read it
fs.readFile(val.path, function (err, data) {
if (err){
console.log("fs " + err);
}
//so until here everything works fine, the files are uploaded to the "/uploads" directory, now im trying to move them to the correct album, the destiation is : public/img/albums/:album_name/:all_images here
mv(val.path, './public/img/albums/' + album_name + '/' + val.path, function(err) {
if (err){
console.log("mv " + err);
}
else{
res.render('admin/panel', {
title: 'אדמין',
message: 'קובץ עלה בהצלחה'
});
res.redirect('/admin');
}
});
});
});
}
});
the mv module throws an error rename "c:/work/xxx/xx/uploads/val.path.png
Its a file-access error. You X out some of the file name, but look at how that NPM module handles file, and ensure you are naming the files and paths properly. Then it should work out fine.
i have used read and write stream and deleted the "mv" module
if (req.body && req.body.album){
var album_name = req.body.album;
}
else{
//need to change to time instead of random album
var album_name = 'unknown_album-' + (parseInt(Math.random() * 5) + 1);
}
//File name
if (req.files.img_file.length > 1)
{
var Counter = 0;
_.each(req.files.img_file,function(val,index){
var file_name = null;
switch(val.type){
case 'image/png':
file_name = new Date().getTime() + '.png';
break;
case 'image/jpeg':
file_name = new Date().getTime() + '.jpeg';
break;
}
mkdirp('./public/img/albums/' + album_name, function (err) {
if (err)
console.error(err);
var source = fs.createReadStream(val.path);
var dest = fs.createWriteStream('./public/img/albums/' + album_name + '/' + val.name);
source.pipe(dest);
source.on('end', function() {
console.log('end...');
Counter++;
console.log(Counter);
console.log(req.files.img_file.length);
if (Counter == req.files.img_file.length){
res.redirect('/admin');
res.render('admin/panel', {
title: 'אדמין',
message: 'קובץ עלה בהצלחה',
albums: albums
}); //eo res render
}
});
source.on('error', function(err) { console.log('error'); });
});// eo mkdir
}); // eo _each
}

Resources