fs.open fails with file extension - node.js - node.js

I've got the following code:
fs.open("uploads/test.txt", "a", "0755", function(err, fd){
if(err) { console.log(err); }
else {
file.handler = fd; //We store the file handler so we can write to it later
...
}
});
The file is created and written to perfectly when I simply have "uploads/test", but when I try to do "uploads/test.txt" it breaks. Any ideas?

I think you should try using
var path = './uploads/test.txt'.
Or
var path = __dirname + 'your_path';
fs.open(path, "a", "0755", function(err, fd){
if(err) { console.log(err); }
else {
file.handler = fd; //We store the file handler so we can write to it later
...
}
});

This is really silly, but I found what was causing my code to break:
fs.open works as intended. The bug was with my file detection setup using nodemon.
The reason is everytime my app would load it would run the above mentioned code. The code would then write to a new file in my apps /uploads directory. Nodemon would then detect the new file and restart the app thus creating a vicious circle.

Related

Node Js saving File but no content

I have a little problem with node js.
If I save a file with fs.writeFile it saves but the file has no content, but if I read the file and print the content there is content in the file
Thats the node js code to save the file:
let sjson = JSON.parse(fs.readFileSync("./saves/User_VipList.json", "utf8"));
sjson['users'].push({"name": args[0]});
fs.writeFile("./saves/User_VipList.json", JSON.stringify(sjson), (err) => {
if(err) throw err;
});
Thats how i read the content:
let sjson = JSON.parse(fs.readFileSync("./saves/User_VipList.json", "utf8"));
console.log(sjson);
And that's the JSON file:
{
"users": []
}
But in users should be content because
Hope you guys can help me
Due to async nature looks like your program doesnt wait when file write ends occurs, so please try to use fs.writeFileSync instead, for example:
try {
fs.writeFileSync("./saves/User_VipList.json", JSON.stringify(sjson))
} catch(err) {
console.log('Error writing file:', err)
}
Found the Problem
Oh i think i found the problem if i start node index.js with a bat file the problem happends but if i start node manually over cmd it works.
Didn't mention the Bat file because i didn't think thats could be a problem :)
But why is that a problem?

gulp plugin looping through all files and folders

OK so I am creating a gulp plugin to create a table of contents and imports for my sass setup.
I have the gulp task all setup like this
var sgc = require('./tasks/sass-generate-contents');
gulp.task('sass-generate-contents', function(){
gulp.src(config.tests + '/**/*.scss')
.pipe(sgc(config.tests + '/_main.scss'));
});
and then my plugin code
function sassGenerateContents(){
return through.obj(function(file, enc, cb){
if (file.isNull()) {
cb(null, file);
return;
}
if (file.isStream()) {
cb(new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'));
return;
}
console.log(file);
});
}
module.exports = sassGenerateContents;
in my file system (the test directory) are 3 x *.scss files
the console log in the plugin only ever returns the first.
I'm probably missing somehting really obvious here, but I thought the idea of **/* was to loop through the folder structure specified and pull out the files.
Can someone explain to me why it's only returning the first file?
Thanks
I was missing the callback function, which called back to itself. At the end of the function i needed to ad
return cb();

NodeJs Method Chaining of fs.mkdir and fs.rename

I'm working on a file uploader script which creates a new folder (based on the timestamp) and moves the uploaded file to the created folder.
Sometimes it works and sometimes I'm getting a ENOENT rename Error (file/folder not exist).
The following code is in my post route:
var form = new multiparty.Form({
uploadDir: "C:"+ path.sep + "files"
});
form.parse(req, function(err, fields, files) {
var dirPath = "C:"+ path.sep + "files" + path.sep + +new Date;
fs.mkdir(dirPath, 0777, function(err, dirPath){
if (err) console.error(err);
console.log("Created new folder");
fs.rename(files.file[i].path, dirPath + path.sep + files.file[i].originalFilename, function(err){
if (err) console.error(err);
console.log("Moved file");
});
}(err, dirPath));
next();
});
I'm using express(4) and the multiparty module.
As you can see I'm using async functions.
So the question is: What is wrong with my code?
Edit
The error I'm talking about: "Error: ENOENT, rename 'C:\files\7384-1r41cry.png'"
It has something to do with a race condition. With fs.mkdirSync everything works fine.
My guess would be some sort of race condition happening here.
This kind of stuff is easy to get wrong and hard to get it right.
I normally use gulp for this kind of stuff and maybe should you :)
To copy a whole directory tree into some other directory wouldn't be easier.
gulp.src('./inputDir/**/*').pipe(gulp.dest('./outputDir')
And all files from inputDir would be copied into outputDir
But maybe coping is not a option. The files could too large, right?
Lets hack it a bit to make it work the way we want.
var fs = require('fs')
, gulp = require('gulp')
, thr = require('through2').obj
, SRC = './test/**/*.{css,html,js}' // it could be 'my/file/located/here'
, OUT = './output' // it could be 'my/newer/file/located/there'
;
gulp.src(SRC)
.pipe(thr(function(chunk, enc, next){
chunk.contents = new Buffer('') // cleaning the contents of the file
chunk._originalPath = chunk.path
next(null, chunk)
}))
.pipe(gulp.dest(OUT))
.pipe(thr(function(chunk, enc, next){
// now a place holder file exists at our destination.
// so we can write to it and being convident it exists
console.log('moving file from', chunk._originalPath, 'to', chunk.path)
fs.rename(chunk._originalPath, chunk.path, function(err){
if (err) return next(err)
next()
})
}))
This moves all css, html and js files from input to output, regardless of how many nested directories there are
gulp is awesome :)
Ok a few things...
you really should start using promises, it makes the code easier to read and the error handling is way superior. I usually use when.js, but there are other alternatives.
you should throw the errors or return on errors or you would try to continue running the function even when the previous operations failed.
you do
if (err) console.error(err);
should be
if (err) throw err;

Meteor/Node writeFile crashes server

I have the following code:
Meteor.methods({
saveFile: function(blob, name, path, encoding) {
var path = cleanPath(path), fs = __meteor_bootstrap__.require('fs'),
name = cleanName(name || 'file'), encoding = encoding || 'binary',
chroot = Meteor.chroot || 'public';
// Clean up the path. Remove any initial and final '/' -we prefix them-,
// any sort of attempt to go to the parent directory '..' and any empty directories in
// between '/////' - which may happen after removing '..'
path = chroot + (path ? '/' + path + '/' : '/');
// TODO Add file existance checks, etc...
fs.writeFile(path + name, blob, encoding, function(err) {
if (err) {
throw (new Meteor.Error(500, 'Failed to save file.', err));
} else {
console.log('The file ' + name + ' (' + encoding + ') was saved to ' + path);
}
});
function cleanPath(str) {
if (str) {
return str.replace(/\.\./g,'').replace(/\/+/g,'').
replace(/^\/+/,'').replace(/\/+$/,'');
}
}
function cleanName(str) {
return str.replace(/\.\./g,'').replace(/\//g,'');
}
}
});
Which I took from this project
https://gist.github.com/dariocravero/3922137
The code works fine, and it saves the file, however it repeats the call several time and each time it causes meteor to reset using windows version 0.5.4. The F12 console ends up looking like this: . The meteor console loops over the startup code each time the 503 happens and repeats the console logs in the saveFile function.
Furthermore in the target directory the image thumbnail keeps displaying and then display as broken, then a valid thumbnail again, as if the fs is writing it multiple times.
Here is the code that calls the function:
"click .savePhoto":function(e, template){
e.preventDefault();
var MAX_WIDTH = 400;
var MAX_HEIGHT = 300;
var id = e.srcElement.id;
var item = Session.get("employeeItem");
var file = template.find('input[name='+id+']').files[0];
// $(template).append("Loading...");
var dataURL = '/.bgimages/'+file.name;
Meteor.saveFile(file, file.name, "/.bgimages/", function(){
if(id=="goodPhoto"){
EmployeeCollection.update(item._id, { $set: { good_photo: dataURL }});
}else{
EmployeeCollection.update(item._id, { $set: { bad_photo: dataURL }});
}
// Update an image on the page with the data
$(template.find('img.'+id)).delay(1000).attr('src', dataURL);
});
},
What's causing the server to reset?
My guess would be that since Meteor has a built-in "automatic directories scanning in search for file changes", in order to implement auto relaunching of the application to newest code-base, the file you are creating is actually causing the server reset.
Meteor doesn't scan directories beginning with a dot (so called "hidden" directories) such as .git for example, so you could use this behaviour to your advantage by setting the path of your files to a .directory of your own.
You should also consider using writeFileSync insofar as Meteor methods are intended to run synchronously (inside node fibers) contrary to the usual node way of asynchronous calls, in this code it's no big deal but for example you couldn't use any Meteor mechanics inside the writeFile callback.
asynchronousCall(function(error,result){
if(error){
// handle error
}
else{
// do something with result
Collection.update(id,result);// error ! Meteor code must run inside fiber
}
});
var result=synchronousCall();
Collection.update(id,result);// good to go !
Of course there is a way to turn any asynchronous call inside a synchronous one using fibers/future, but that's beyond the point of this question : I recommend reading this EventedMind episode on node future to understand this specific area.

Node.JS - fs.exists not working?

I'm a beginner in Node.js, and was having trouble with this piece of code.
var fs = require('fs');
Framework.Router = function() {
this.run = function(req, res) {
fs.exists(global.info.controller_file, function(exists) {
if (exists) {
// Here's the problem
res.writeHead(200, {'Content-Type':'text/html'});
var cname = App.ucfirst(global.info.controller)+'Controller';
var c = require(global.info.controller_file);
var c = new App[cname]();
var action = global.info.action;
c[action].apply(global.info.action, global.info.params);
res.end();
} else {
App.notFound();
return false;
}
});
}
};
The problem lies in the part after checking if the 'global.info.controller_file' exists, I can't seem to get the code to work properly inside the: if (exists) { ... NOT WORKING }
I tried logging out the values for all the variables in that section, and they have their expected values, however the line: c[action].apply(global.info.action, global.info.params);
is not running as expected. It is supposed to call a function in the controller_file and is supposed to do a simple res.write('hello world');. I wasn't having this problem before I started checking for the file using fs.exists. Everything inside the if statement, worked perfectly fine before this check.
Why is the code not running as expected? Why does the request just time out?
Does it have something to do with the whole synchronous vs asynchronous thing? (Sorry, I'm a complete beginner)
Thank you
Like others have commented, I would suggest you rewrite your code to bring it more in-line with the Node.js design patterns, then see if your problem still exists. In the meantime, here's something which may help:
The advice about not using require dynamically at "run time" should be heeded, and calling fs.exists() on every request is tremendously wasteful. However, say you want to load all *.js files in a directory (perhaps a "controllers" directory). This is best accomplished using an index.js file.
For example, save the following as app/controllers/index.js
var fs = require('fs');
var files = fs.readdirSync(__dirname);
var dotJs = /\.js$/;
for (var i in files) {
if (files[i] !== 'index.js' && dotJs.test(files[i]))
exports[files[i].replace(dotJs, '')] = require('./' + files[i]);
}
Then, at the start of app/router.js, add:
var controllers = require('./controllers');
Now you can access the app/controllers/test.js module by using controllers.test. So, instead of:
fs.exists(controllerFile, function (exists) {
if (exists) {
...
}
});
simply:
if (controllers[controllerName]) {
...
}
This way you can retain the dynamic functionality you desire without unnecessary disk IO.

Resources