sharp constructor won't take a variable as file path input when try to resize image - [input file missing error] - node.js

it is quite strange that when passing a String variable to sharp() as file path input always gives me this error -
[Error: Input file is missing or of an unsupported image format]
I even add toString() to my variable so my return is for sure a string.
var tmp = 'image/'+ id + '.jpg';
var path = tmp.toString();
console.log("What's in tmp: " + tmp);
console.log("What's in path: " + path);
sharp(path)
.resize(300, 300)
.toFile('image/'+ id + 'L.jpg', function(err, info) {
if (err) {
console.log('Error Type: ', err);
}
});
The way I verified my code is following:
It works the other way so my image format is correct. I even do a 'sharp.format' to confirm its support so it's not the problem here. Next I copy the 'path' variable string from my console log output and paste it directly inside sharp constructor call = sharp().
Console OUTPUT:
What's in a tmp: image/1.jpg
What's in a path: image/1.jpg
sharp('image/1.jpg')
.resize(300, 300)
.toFile('image/'+ id + 'L.jpg', function(err, info) {
if (err) {
console.log('Error Type: ', err);
}
});
Now everything starts working again - file is resized and generated in image. Switching back using 'path' variable continue gives me no luck. It surprises me with this kind of issue because it clearly stated in their document that it supports a String type input. Also now I'm confused with the difference between path and 'image/1.jpg'. Maybe my next step is to use ( path === 'image/1.jpg' ) to compare them.
Statement from sharp doc for your reference -->
'input (Buffer | String)? or a String containing the path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.'
It must be something obvious I missed. I am sure that when they design the tool, they give user the flexibility to define their input path as a variable for code reuse. So any suggestion? Thanks in advance.

Related

Node.js fs.writeFile() not creating new files?

I need to create many .json files for the system i am trying to develop. To do this, i ran a for loop over the file names i needed, then used fs.writeFileSync('filename.json', [data]).
However, when trying to open these later, and when I try to find them in the project folder, I cannot find them anywhere.
I have tried writing in a name that was less complex and should have appeared in the same directory as my script, however that was fruitless as well. To my understanding, even if my file name wasn't what I expected it to be, I should get at least something, somewhere, however I end up with nothing changed.
My current code looks like this:
function addEmptyDeparture(date) {
fs.readFileSync(
__dirname + '/reservations/templates/wkend_dep_template.json',
(err, data) => {
if (err) throw err
fs.writeFileSync(
getDepartureFileName(date),
data
)
}
)
}
function getDepartureFileName(date){
return __dirname + '/reservations/' +
date.getFullYear() +
'/departing/' +
(date.getMonth() + 1).toString().padStart(2, "0") +
date.getDate().toString().padStart(2, "0") +
'.json'
}
Where data is the JSON object returned from fs.readFileSync() and is immediately written into fs.writeFileSync(). I don't think I need to stringify this, since it's already a JSON object, but I may be wrong.
The only reason I think it's not working at all (as opposed to simply not showing up in my project) is that, in a later part of the code, we have this:
fs.readFileSync(
getDepartureFileName(date)
)
.toString()
which is where I get an error for not having a file by that name.
It is also worth noting that date is a valid date object, as I was able to test that part in a fiddle.
Is there something I'm misunderstanding in the effects of fs.writeFile(), or is this not the best way to write .json files for use on a server?
You probably are forgetting to stringify the data:
fs.writeFileSync('x.json', JSON.stringify({id: 1}))
I have tried to create similar case using a demo with writeFileSync() creating different files and adding json data to these ,using a for loop. In my case it works . Each time a new file name is created . Here is my GitHub for the same :-
var fs = require('fs');
// Use readFileSync() method
// Store the result (return value) of this
// method in a variable named readMe
for(let i=0 ; i < 4 ; i++) {
var readMe = JSON.stringify({"data" : i});
fs.writeFileSync('writeMe' + i + '.json', readMe, "utf8");
}
// Store the content and read from
// readMe.txt to a file WriteMe.txt
Let me know if this what you have been trying at your end.

Switch to what ever path is input nodejs

Lets assume you have installed an electron app and you are asked to input the path to your current project. You might do something like: ~/Documents/projectName.
How do I, in node take that input and check if it exists, specifically if you entered in the path as shown above?
the reason for this is that I want to see if A) the path exists and B) if theres a specific file there (I'll be using path.join(dirEntered, fileName.extension).
Is there a way to do what I want? I see chdir but that changes where the working directory is. which I guess would be fine but doing:
process.chdir('~/Documents') Shows: no such file or directory, uv_chdir(…)
I want to avoid having the user to enter the full absolute path of their project. That seems "bad to me". And uploading their project isn't necessary, Im reading a single file (so theres no need for upload here).
Any ideas?
Is it possible to tap into the cli commands and take this input feed it there and get the result? Or is that over kill?
Here's an idea how to solve it. If the path starts with a tilde, it replaces that tilde with the full home directory of the current user. It then uses fs.stat to see if the given path actually exists.
const fs = require("fs");
const os = require("os");
var path = "~/Documents";
if (path.indexOf("~") === 0) {
path = os.homedir() + path.substring(1);
}
fs.stat(path, (err, stats) => {
if (!err) {
// document or path exists
if (stats.isFile()) {
console.log("Path " + path + " is a file");
} else if (stats.isDirectory()) {
console.log("Path " + path + " is a directory");
}
} else {
// document or path does not exist
}
});

ENOENT using fs.appendFile()

I am trying to append data into some files.
Docs says fs.appendFile:
Asynchronously append data to a file, creating the file if it not yet exists, data can be a string or a buffer
function appendData(products) {
var productsPromises = products.map(function(product) {
var title = product['title'];
return fs.appendFile('/XXXXX/' + title, product, 'utf8', function(err){
console.log(err);
});
});
return Promise.all(productsPromises);
}
I am getting Error:
ENOENT, open '/XXXXX/PPPPPPPP'
What am i doing wrong?
You might have accidently added / in front of XXXXX.
I you expect it to write to a folder XXXXX which is located in the same place of where you launched the application, then change your code to:
return fs.appendFile('XXXXX/' + title, product, 'utf8', function(err){
As / In front means root of your filesystem, and the error is common of path does not exist. I.e. there is no XXXXX in root of your filesystem, as #Rahil Wazir said.
The problem was that i forgot to add the dot.
Should be:
return fs.appendFile('./XXXXX/' + title, product, 'utf8', function(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.

what does the filename option do in stylus.render function?

I have tried to change the filename parameter as per the sample codes (from official documentation) given below but it does not have any impact on my output.
I would expect that the filename would specify the path to either input or the output. However str is the input and needs to be defined and no output file gets generated based on the filename parameter.
So what does the filename option do in stylus.render function ?
Sample code from
var css = require('../')
, str = require('fs').readFileSync(__dirname + '/basic.styl', 'utf8');
css.render(str, { filename: 'basic.styl' }, function(err, css){
if (err) throw err;
console.log(css);
});
Sample code from
var stylus = require('stylus');
stylus.render(str, { filename: 'nesting.css' }, function(err, css){
if (err) throw err;
console.log(css);
});
The filename parameter is used in error reporting, not as an input or output filename.
From the docs at http://learnboost.github.io/stylus/docs/js.html:
Simply require the module, and call render() with the given string of Stylus code, and (optional) options object.
Frameworks utilizing Stylus should pass the filename option to provide better error reporting.

Resources