Error with NodeJS FS (writeFile) - javascript

Here is my piece of my router who manage my uploads :
fs.readFile(files.photo.path, function (err, data) {
// Here is the futur name of my file (ex: SERVER_PATH/images/moka/moka22/11/2016_1.jpg)
var newPath = __dirname + "/images/moka/moka" + new Date().toLocaleDateString() + "_" + Math.floor(Math.random() * 10) + 1 + "." + ext;
fs.writeFile(newPath, data, function (err) {
if(err) {
res.render('error', { error: err, message: "Erreur lors de l'upload"});
} else {
// insctructions
});
}
});
});
When the code is triggered I have this error :
Error: ENOENT: no such file or directory, open 'D:\projects\raspberry\routes\images\moka\moka2016-11-22_91.jpg'
at Error (native)
If I well understood the fs doc (https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback) :
fs.writeFile(theNameOfTheFuturFile, theDataToPutIn, callback);
So I'm a bit confused.
Sorry for my english, it may be bad, i hope that you guess what i mean :)
Thanks.

The problem could be the directory you are writing to does not exist.
so make sure it exists:
fs.readFile(files.photo.path, function (err, data) {
var dirPath = __dirname + "/images/moka/moka";
if (!fs.existsSync(dirPath)){
fs.mkdirSync(dirPath);
}
...
or do it by hand.

Related

What is a UnhandledPromiseRejectionWarning: ReferenceError in Node Javascript?

I had working express Node Javascript code, but when I changed the code to give me a random id for each file input (instead of a set file name, myFile.jpeg), I get the following error:
UnhandledPromiseRejectionWarning: ReferenceError: fileName is not defined
I know that I've defined the fileName, but I don't understand what this error means or how to fix it. I've seen this error a lot of Discord bots or MongoDB, but I'm having a hard time finding anything for express.
let rid = Math.floor(Math.random() * 10000000)
let ridString = "" + rid
//const upload = multer().single('myfile')
const upload = multer().single(ridString)
//other code
app.post('/upload', (req, res)=>{
upload(req, res, async function(err){
if( err|| req.file === undefined){
console.log(err)
res.send("error occured")
}else{
//let rid = Math.floor(Math.random() * 10000000)
//let ridString = "" + rid
let fileName = ridString + ".jpeg"
//let fileName = "myfile.jpeg"
var image = await sharp(req.file.buffer)
//.catch(err => {console.log('error: ', err)})
.jpeg({
//quality: 40,
}).toFile('./uploads/'+fileName)
.catch( err => { console.log('error: ', err) })
pythonFunction(res, fileName);
}
})
})
I've commented out everything that got changed from myFile to the random number.

Reading and Writing files async in node.js

Currently i'm reading and writing files asynchronously, the thing is that i'm not sure that all the line from the file were read before the rest of my code is executed, here is my code:
var fs = require('fs');
//var str = fs.readFileSync("stockststs.json");
function updateJson(ticker) {
//var stocksJson = JSON.parse(fs.readFileSync("stocktest.json"));
fs.readFile('stocktest.json', function(error, file) {
stocksJson = JSON.parse(file);
if (stocksJson[ticker]!=null) {
console.log(ticker+" price : " + stocksJson[ticker].price);
console.log("changin the value...")
stocksJson[ticker].price = 989898;
console.log("Price after the change has been made -- " + stocksJson[ticker].price);
fs.writeFile('stocktest.json',JSON.stringify(stocksJson, null, 4) , function(err) {
if(!err) {
console.log("File successfully written");
}
});
}
else {
console.log(ticker + " doesn't exist on the json");
}
});
}
updateJson("APPL");
I'm wondering if there is any better way to to implement ?
its always a good practice to check in your callback for error. For example, i have written a small getCache function that checks if the file exists first, then tries to read that file and fire a callback afterwards
Cache.prototype.getCache = function(cache_filename, callback) {
cache_filename = this.cache_foldername + cache_filename;
fs.exists(cache_filename, function(exists) {
if (exists) {
fs.readFile(cache_filename, 'utf8', function (error, data) {
if (!error) {
console.log('File: '+ cache_filename +' successfully Read from Cache!');
_.isObject(data) ? callback(null,data) : callback(null,JSON.parse(data));
} else console.log("Error Reading Cache from file: " + cache_filename + " with Error: " + error);
});
} else callback(null,false);
});
}
note that in here what you need to do is to write the file after it has been read and checked with the if (!error)
i hope this helps

Strange error while deleting a file using the module fs in node js

I'm trying to delete some files in a folder using the module fs.
I need to delete a file only if it is older (modified time) that 1 minute.
But I get a strange error.
var fs = require("fs");
var files = fs.readdirSync("./folder");
for (var i in files) {
fs.stat("./folder/" + files[i], function (err, stats) {
var currentTimestamp = Math.round(new Date().getTime() / 1000);
var fileTimestamp = Math.round((new Date(stats.mtime).getTime() / 1000));
if ((currentTimestamp - fileTimestamp) > 60 * 1) {
//Elimino il file di cache
fs.unlinkSync("./folder/" + files[i], function (err) {
if (err) {
console.log(err);
} else {
console.log("File deleted");
}
});
}
});
}
Unfortunately I get this error
fs.js:765
return binding.unlink(pathModule._makeLong(path));
^
Error: ENOENT, no such file or directory
Why does this happen?
How can I solve ??
Thanks
EDIT
I make a log before the fs.unlinkSync("./folder/" + files[i], function (err) and I see that is called 2 times with the same file... but there is only one file in the folder.... with that name
Below is the problem:-
You are doing fs.stat an async call in for loop. And for is a sync block. There are chances that it will be called after the end of your for loop. In the end, it will call all callbacks with last value of i.
Since value of i is same it will search for the same file more than once and it will end up throwing an error.
There are two solutions to your problem.
1) Use fs.statSync & fs.unlinkSync so it will be sync call. The value of i won't increment until the whole loop executes, but it's not the good way of doing it.
2) Use Array.forEach because it is an async process, so it will call the function on each file. I will prefer this method.
I've modified your problem and got it working with Array.forEach.
var fs = require("fs");
var files = fs.readdirSync("./Folder");
var deleteFile = function (fileName) {
fs.stat("./Folder/" + fileName, function (err, stats) {
var currentTimestamp = Math.round(new Date().getTime() / 1000);
var fileTimestamp = Math.round((new Date(stats.mtime).getTime() / 1000));
if ((currentTimestamp - fileTimestamp) > 60 * 1) {
//Elimino il file di cache
console.log('deleting ',fileName)
fs.unlink("./Folder/" + fileName, function (err) {
if (err) {
console.log(err);
} else {
console.log("File deleted");
}
});
}
});
}
files.forEach(deleteFile);

Crypto module - Node.js

Which is the simplest way to compare a hash of a file without storing it in a database?
For example:
var filename = __dirname + '/../public/index.html';
var shasum = crypto.createHash('sha1');
var s = fs.ReadStream(filename);
s.on('data', function(d) {
shasum.update(d);
});
s.on('end', function() {
var d = shasum.digest('hex');
console.log(d + ' ' + filename);
fs.writeFile(__dirname + "/../public/log.txt", d.toString() + '\n', function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
});
The above code returns the hash of the HTML file. If I edit the file how can I know if it has been changed? In other words, how can I know if the hash has been changed?
Any suggestions?
Edited
Now the hash is being saved in the log file. How can I retrieve the hash from the file and match it with the new generated one? A code example would be awesome to give me a better understanding.
There is no difference with this question, but it isn't clear for me yet how to implement it.
If you're looking for changes on a file, then you can use one of Node's filesystem functions, fs.watch. This is how it's used:
fs.watch(filename, function (event, filename) {
//event is either 'rename' or 'change'
//filename is the name of the file which triggered the event
});
The watch function is however not very consistent, so you can use fs.watchFile as an alternative. fs.watchFile uses stat polling, so it's quite a bit slower than fs.watch, which detects file changes instantly.
Watching a file will return an instance of fs.FSWatcher, which has the events change and error. Calling .close will stop watching for changes on the file.
Here's an example relating to your code:
var filename = __dirname + '/../public/index.html';
var shasum = crypto.createHash('sha1');
var oldhash = null;
var s = fs.ReadStream(filename);
s.on('data', function(d) {
shasum.update(d);
});
s.on('end', function() {
var d = shasum.digest('hex');
console.log(d + ' ' + filename);
oldhash = d.toString();
fs.writeFile(__dirname + "/../public/log.txt", d.toString() + '\n', function(err) {
if(err) {
console.log(err);
}
else {
console.log("The file was saved!");
}
});
});
//watch the log for changes
fs.watch(__dirname + "/../public/log.txt", function (event, filename) {
//read the log contents
fs.readFile(__dirname + "/../public/log.txt", function (err, data) {
//match variable data with the old hash
if (data == oldhash) {
//do something
}
});
});
What's the difference between this question and the previous one you asked? If you're not wanting to store it in a database, then store it as a file. If you want to save the hash for multiple files, then maybe put them in a JSON object and write them out as a .json file so they're easy to read/write.
EDIT
Given what you added to your question, it should be pretty simple. You might write a function to do check and re-write:
function updateHash (name, html, callback) {
var sha = crypto.createHash('sha1');
sha.update(html);
var newHash = sha.digest('hex');
var hashFileName = name + '.sha';
fs.readFile(hashFileName, 'utf8', function (err, oldHash) {
var changed = true;
if (err)
console.log(err); // probably indicates the file doesn't exist, but you should consider doing better error handling
if (oldHash === newHash)
changed = false;
fs.writeFile(hashFileName, newHash, { encoding: 'utf8' }, function (err) {
callback(err, changed);
});
});
}
updateHash('index.html', "<html><head><title>...", function (err, isChanged) {
// do something with this information ?
console.log(isChanged);
});

node.js & Express fs.rename random Error: EPERM, operation not permitted ! how to fix it?

i got a problem with the fs.rename function! Sometimes it doesn´t works and i don´t know why. I try to upload some files and rename it! So it should be work for a time.
in the codes below:
exports.up = function(req, res){
var len = [].concat(req.files.fileSelect);
for(var i = 0; i < len.length; i++) {
var tmp_path =(len[i].path);
if(len[i].name ==''){
len[i].name ='empty';
}
console.log(len[i]);
var target_path =('./public/images/' + len[i].name);
fs.rename(tmp_path, target_path, function(err) {
if (err) throw err;
fs.unlink(tmp_path, function() {
if (err) throw err;
});
});
}
res.redirect('/picture');
};

Categories