Download image and resize in nodejs - node.js

What I am trying to do is download an image from google into my system repository in the project folder /download. Next, I am trying to get the image from the download repository and resize and again save the resized image in /thumbnail repository. Below is the code which I have written
//Google URL
var mainuri = 'http://images.sadhguru.org/sites/default/files/media_files/iso/en/64083-natures-temples.jpg';
var dir = './download';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
// CODE TO DOWNLOAD IMAGE FROM GOOGLE
var filename = dir+'/file.jpg';
request.head(mainuri, function(err, res, body){
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(mainuri).pipe(fs.createWriteStream(filename));
});
var resizedir = './thumbnail';
if (!fs.existsSync(resizedir)){
fs.mkdirSync(resizedir);
}
//CODE TO GET IMAGE FROM '/download' REPOSITORY AND RESIZE
var inputFile=require('path').join(__dirname,'../download/file.jpg'); //GET IMAGE FROM LOCAL
var outFile = 'thumbnail/newfile.jpg'; // SAVE RESIZED IMAGE PATH
// ------- CODE REMOVED - ERROR IS COMING HERE -----------
imageresize(inputFile, outFile); // FUNCTION THAT CONTAINS IMAGE RESIZE CODE
//imageresize FUNCTION
var imageresize = function(inputFile, outFile){
console.log(inputFile)
// input stream
let inStream = fs.createReadStream('C:/Users/rganji/caw/server/download/file.jpg');
// output stream
let outStream = fs.createWriteStream(outFile, {flags: "w"});
// on error of output file being saved
outStream.on('error', function() {
console.log("Error");
});
// on success of output file being saved
outStream.on('close', function() {
console.log("Successfully saved file");
});
// input stream transformer
// "info" event will be emitted on resize
let transform = sharp()
.resize({ width: 50, height: 50 })
.on('info', function(fileInfo) {
console.log("Resizing done, file not saved");
});
inStream.pipe(transform).pipe(outStream);
}
If I remove the code which I commented as CODE REMOVED - ERROR IS COMING HERE, then image is getting downloaded from google. If I call imageresize function then the /download directory is getting created but I couldnt find any image in the directory.
i.e, If I call the download from google and resizeimage functions separately, i.e calling image download from google first and imageresize next then they are working fine that is I can find images in both /download and /thumbnail directories. But If I call resizeimage function after google download then I couldnt find any image in both the repositories.

You need to wait for the image download to get finished before calling the imageresize function. Try this
request(mainuri).on('end', function() {
var inputFile=require('path').join(__dirname,'../download/file.jpg'); //GET IMAGE FROM LOCAL
var outFile = 'thumbnail/newfile.jpg'; // SAVE RESIZED IMAGE PATH
imageresize(inputFile, outFile);
});

Related

After upload a media file can not play the file in angular 2, shows 404 not found

I have a problem in Angular2: I have module for media upload (Images/Videos). So upload module is working perfect but after uploading the file when I try to watch the video or view the image file, I get a 404 Not Found error. But if i run ng build and refresh it again I can watch the video or view the image files. Am i doing something wrong or we can handle this with someway?
GET http://localhost:4200/dist/assets/mediauploads/Desktop%20(19).jpg 404 (Not Found)
//This is my node js code
socket.on('Upload', function (data){
var Name = data['Name'];
Files[Name]['Downloaded'] += data['Data'].length;
Files[Name]['Data'] += data['Data'];
if(Files[Name]['Downloaded'] == Files[Name]['FileSize']) //If File is Fully Uploaded
{
fs.write(Files[Name]['Handler'], Files[Name]['Data'], null, 'Binary', function(err, Writen){
var inp = fs.createReadStream("./src/assets/temp/" + Name);
var out = fs.createWriteStream("./src/assets/mediauploads/" + Name);
inp.pipe(out);
inp.on("end", function() {
var path="./src/assets/temp/" + Name;
var tempFile = fs.openSync(path, 'r');
if(fs.existsSync(path)){
fs.closeSync(tempFile);
fs.unlinkSync(path);
socket.emit('Done', {'Image' : './src/assets/mediauploads/' + Name});
}
});
});
}
else if(Files[Name]['Data'].length > 10485760){ //If the Data Buffer reaches 10MB
fs.write(Files[Name]['Handler'], Files[Name]['Data'], null, 'Binary', function(err, Writen){
Files[Name]['Data'] = ""; //Reset The Buffer
var Place = Files[Name]['Downloaded'] / 524288;
var Percent = (Files[Name]['Downloaded'] / Files[Name]['FileSize']) * 100;
socket.emit('MoreData', { 'Place' : Place, 'Percent' : Percent});
});
}
else
{
var Place = Files[Name]['Downloaded'] / 524288;
var Percent = (Files[Name]['Downloaded'] / Files[Name]['FileSize']) * 100;
socket.emit('MoreData', { 'Place' : Place, 'Percent' : Percent});
}
});
When you run ng build the angular app is built into the dist folder. My guess is you have your app setup in such a way you are actually uploading the image into your src/assets folder.
As you are running the app from the dist folder your newly uploaded image/video is not visible. When you rebuild the app the file is copied to the dist folder and becomes accesible.

Check uploaded file extension in Sails js

How we can check uploaded file extension in sails js?
I tried on skipper and multer but have no result.
any suggestion?
You should use saveAs options for each file before saving.
var md5 = require('md5');
module.exports = {
testUpload:function(req,res){
// setting allowed file types
var allowedTypes = ['image/jpeg', 'image/png'];
// skipper default upload directory .tmp/uploads/
var allowedDir = "../../assets/images";
// don not define dirname , use default path
req.file("uploadFiles").upload({
saveAs:function(file, cb) {
var d = new Date();
var extension = file.filename.split('.').pop();
// generating unique filename with extension
var uuid=md5(d.getMilliseconds())+"."+ extension;
// seperate allowed and disallowed file types
if(allowedTypes.indexOf(file.headers['content-type']) === -1) {
// save as disallowed files default upload path
cb(null,uuid);
}else{
// save as allowed files
cb(null,allowedDir+"/"+uuid);
}
}
},function whenDone(err,files){
return res.json({
files:files,
err:err
});
});
}
}
Just get uploaded files array and check last chunk of string after dot.
req.file('file').upload({
maxBytes: 2000000,
dirname: 'uploadFolder'
}, function (error, files) {
if (error) return sails.log.error(error);
// You have files array, so you can do this
files[0].fd.split('.').pop(); // You get extension
}
What is going on here? When upload is finished you will get array of files with their filenames. You can get data from that array and see where this file is located (full path).
The last thing is splitting string by dots and get last item from the array with pop() method.

Write text on existing PNG with Node.js

I'm trying to create a simple dynamic-badge (png) to embed in static pages to let know the status of my application.
I'd like so to use an existing PNG image and write on it some text with Node.js.
I've found lot of libraries but all of them use Imagemagick or Cairo as native dependencies, I'd like to avoid to install anything else on the server.
I've then found lwip, but I can't really understand how to write text on an image with it. How can I do?
You could use Jimp. It has a print method:
var Jimp = require("jimp");
var fileName = 'test.png';
var imageCaption = 'Image caption';
var loadedImage;
Jimp.read(fileName)
.then(function (image) {
loadedImage = image;
return Jimp.loadFont(Jimp.FONT_SANS_16_BLACK);
})
.then(function (font) {
loadedImage.print(font, 10, 10, imageCaption)
.write(fileName);
})
.catch(function (err) {
console.error(err);
});
If you want to use a ttf file you can use gm
This will also align the text automatically so you don't have to keep track of your letter sizing / location.
const gm = require('gm').subClass({imageMagick: true});
gm('path/to/image.png')
.fill("#FFFFFF")
.font("./font.ttf", 20)
.drawText(15, 10, "your text", 'southeast') //can be any location
.write("./output.png", function (err) {
if (!err) console.log('done');
});

Get file size of GIFs with node-canvas?

After much struggling, I've managed to get node-canvas installed on Windows.
When I try to read in the image size of a GIF, however, it just gives me back 0 for the width and height.
var FileSystem = require('fs');
var Canvas = require('canvas');
FileSystem.readdir(baseDir, function(err, files) {
files.forEach(function(filename) {
var path = Path.join(baseDir, filename);
FileSystem.readFile(path, function(err, buf) {
var img = new Canvas.Image;
img.src = buf;
console.log(path, img.width, img.height);
});
});
Is it not supposed to be able to read GIFs?
You must install giflib and reinstall node-canvas like is said in here https://github.com/LearnBoost/node-canvas/wiki/Installation---OSX and then you will be able to manipulate your gif file (retrieve width/height). But beware, the image processed with canvas will stop being animated.

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.

Resources