How can I use remote image in ImageMagick with Node.JS?
I want to achieve something like:
im.identify('http://www.website.com/image.jpg', function(error, features) {
console.log(features);
});
A quick code snippet of image resizing
http://nodejs.org/api/http.html
https://github.com/rsms/node-imagemagick
var thumb = '';
...
var request = http.get(options, function(response) {
var data = '';
response.setEncoding('binary');
response.on('data', function(chunk) {
data += chunk;
});
response.on('end', function () {
im.resize({
srcData: data,
width: 100,
height: 75,
format: 'jpg'
}, function(err, stdout, stderr) {
if (err) throw err;
thumb = stdout;
});
}
});
This is how I use remote images:
var srcUrl = 'http://domain.com/path/to/image.jpg';
var http = srcUrl.charAt(4) == 's' ? require("https") : require("http");
var url = require("url");
http.get(url.parse(srcUrl), function(res) {
if(res.statusCode !== 200) {
throw 'statusCode returned: ' + res.statusCode;
}
else {
var data = new Array;
var dataLen = 0;
res.on("data", function (chunk) {
data.push(chunk);
dataLen += chunk.length;
});
res.on("end", function () {
var buf = new Buffer(dataLen);
for(var i=0,len=data.length,pos=0; i<len; i++) {
data[i].copy(buf, pos);
pos += data[i].length;
}
im(buf).imFunctionYouWantToUse();
});
}
});
Credit go to https://stuk.github.io/jszip/documentation/howto/read_zip.html
It's hard to say if i understood you correctly (considering the amount of information you posted here).
The only way you can perform operations on a remote image using imagemagick is to download it to the local server first. This can be done using the http.ClientRequest class of node.js, afterwards you should be able to operate on the image as usual using Imagemagick.
This should work:
var request = require('request');
var fs = require('fs');
request({
'url': 'http://www.website.com/image.jpg',
'encoding':'binary'
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
fs.writeFileSync('/mylocalpath/image.jpg', body, 'binary');
im.identify('/mylocalpath/image.jpg',
function(error, features) {
console.log(features);
}
);
}else{
console.error(error, response);
}
}
)
Related
Well, i'm visiting an array of urls making a request for each one, when one request ends the method executes the next. The array is something like this: [link1,link2,link3]. If i try to open first the link3 in browser i'll get an error (error 404) but opening the link1 and link2 first i'll have the desired response. In the browser works without problems, but isn't working in my code because i got "status:200" using the first two links, but a 404 with the third.
(If i open link2 and link2 in the browser the problem ends, but i want to do that not using the browser)
The code:
function websiteOpener(links_array, index, final) {
var methodStr = className + '::websiteOpener';
try {
log.info(methodStr + '>> Open the link: ' + links_array[index]);
var protocol;
var _host;
var rawhost;
if (links_array[index].match(/https:\/\/[^\/]+/)) {
rawhost = links_array[index].match(/https:\/\/[^\/]+/);
_host = rawhost[0].replace(/https:\/\//, '');
protocol = 'https:'
_path = links_array[index].replace(rawhost, '');
incremental = index + 1;
var options = {
host: _host,
path: _path,
method: 'GET',
headers: { 'Content-type': 'text/html' },
protocol: protocol,
agent: new https.Agent({
rejectUnauthorized: false,
})
}
} else {
incremental = index + 1;
var options =links_array[index];
}
if (incremental < final) {
if (links_array[index].match(/https:\/\/[^\/]+/)) {
var request = https.request(options, function (response) {
console.log(response.statusCode);
//if (response.statusCode === 200) {
var data;
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', function () {
websiteOpener(links_array, incremental, final);
});
//}
});
request.end();
} else {
var request = http.request(options, function (response) {
//if (response.statusCode === 200) {
var data;
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', function () {
websiteOpener(links_array, incremental, final);
});
//}
});
request.end();
}
} else {
options.headers = { 'Content-type': 'applcation/pdf' };
var request = https.request(options, function (response) {
console.log(response.statusCode);
//if (response.statusCode === 200) {
var data;
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', function () {
log.info(methodStr + '>>link found ' + links_array[index]);
});
//}
});
request.end();
}
} catch (e) {
log.error(methodStr + ">> Server error: ", e);
reject({ statusCode: 500, flag: 'ERR_PROCESS' });
}
}
Following is the node-js code used for HTTP requests. This code is giving "This deferred has already been resolved" error on production servers when I try to use requestPromise.resolve(str) in request end. Can someone please suggest what might be the error?
Libraries used : http and node-promise
var Promise = require('node-promise').Promise;
var requestPromise = new Promise();
callback = function (response) {
var str = '';
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
if (!(response && response.statusCode >= 200 && response.statusCode < 300)) {
requestPromise.resolve(str);
return;
}
var resp;
try {
resp = JSON.parse(str);
} catch (ex) {
resp = str;
}
requestPromise.resolve(str);
});
});
var request = http.request(options, callback);
request.on('error', function (err) {
requestPromise.resolve(err);
});
request.write(postObject);
request.end();
I think you cannot use new Promise() (because it need resolver).
You can use this code:
new Promise(function(resolve, reject) {
callback = function (response) {
var str = '';
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
if (!(response && response.statusCode >= 200 && response.statusCode < 300)) {
resolve(str);
return;
}
var resp;
try {
resp = JSON.parse(str);
} catch (ex) {
resp = str;
}
resolve(resp);
});
});
var request = http.request(options, callback);
request.on('error', function (err) {
reject(err);
});
request.write(postObject);
request.end();
});
var exports = module.exports = {};
var http = require('http');
exports.get = function(key, app, vari) {
http.get('<url here>/?key='+key+'&app='+app+'&var='+vari+'&req=0', function (response) {
response.setEncoding('utf8');
response.on('data', function(body) {
console.log(body);
return body;
});
});
};
My code (seen above) will output the response to the console just fine, but when trying to use the function in an export, it returns 'undefined' no matter what. The responses it receives are one line and are in the content type of "application/json". What's up with it? (And no, it's not the "url here", I just removed the URL for privacy reasons. If it helps, I can provide it.)
exports.get = function(key, app, vari) {
return
http.get('<url here>/?key='+key+'&app='+app+'&var='+vari+'&req=0', function (response) {
response.setEncoding('utf8');
response.on('data', function(body) {
console.log(body);
return body;
});
});
};
reference,and you need to listen end event and return a promise instead, just like:
var exports = module.exports = {};
var http = require('http');
exports.get = function(key, app, vari) {
return new Promise(function(resolve) {
http.get('<url here>/? key='+key+'&app='+app+'&var='+vari+'&req=0', function (response) {
response.setEncoding('utf8');
var data = '';
response.on('data', function(chunk) {
console.log(chunk);
data += chunk;
});
response.on('end', function() {
resolve(JSON.parse(data));
});
});
})
}
I figured it out, I just needed to have a call for an answer.
var exports = module.exports = {};
var http = require('http');
exports.get = function(key, app, vari, answ) {
http.get('http://<url here>/?key='+key+'&app='+app+'&var='+vari+'&req=0', function (response) {
response.setEncoding('utf8');
response.on('data', function(body) {
answ(body);
});
});
};
function media(req,res){
console.log(req.query.image);
var collectionName = 'imageTable';
var selector = MongoHelper.idSelector(req.query.image);
MongoHelper.findOne(selector, collectionName, function(err, image) {
console.log(image.picture);
var url_parts = url.parse(image.picture);
var options = {host: url_parts.hostname, path: url_parts.pathname};
http.get(options).on('response', function (response) {
var body = '';
var i = 0;
response.on('data', function (chunk) {
i++;
body += chunk;
console.log('BODY Part: ' + i);
});
response.on('end', function () {
console.log('Finished');
res.writeHead(200,{'Content-Type':'image/JPEG'});
res.write(body);
res.end();
});
});
});
}
I am fetching image from different server. I have url of that image. And I am writing the response. But here response image is get corrupted. Any idea about how to write jpeg image in response?
function media(req,res){
console.log(req.query.image);
var collectionName = 'facebook';
var selector = MongoHelper.idSelector(req.query.image);
MongoHelper.findOne(selector, collectionName, function(err, image) {
var url_parts = url.parse(image.picture);
var options = {host: url_parts.hostname, path: url_parts.pathname};
http.get(options).on('response', function (response) {
res.writeHead(200,{'Content-Type':'image/JPEG'});
response.on('data', function (chunk) {
res.write(chunk);
});
response.on('end', function () {
res.end();
});
});
});
}
Here I got the solution. Instead of writing whole data at the end. Write it each time you get and end the response when you reach to the end of file. But still if anyone have better idea can write here.
Whats the best way to read a remote file? I want to get the whole file (not chunks).
I started with the following example
var get = http.get(options).on('response', function (response) {
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
I want to parse the file as csv, however for this I need the whole file rather than chunked data.
I'd use request for this:
request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))
Or if you don't need to save to a file first, and you just need to read the CSV into memory, you can do the following:
var request = require('request');
request.get('http://www.whatever.com/my.csv', function (error, response, body) {
if (!error && response.statusCode == 200) {
var csv = body;
// Continue with your processing here.
}
});
etc.
You can do something like this, without using any external libraries.
const fs = require("fs");
const https = require("https");
const file = fs.createWriteStream("data.txt");
https.get("https://www.w3.org/TR/PNG/iso_8859-1.txt", response => {
var stream = response.pipe(file);
stream.on("finish", function() {
console.log("done");
});
});
http.get(options).on('response', function (response) {
var body = '';
var i = 0;
response.on('data', function (chunk) {
i++;
body += chunk;
console.log('BODY Part: ' + i);
});
response.on('end', function () {
console.log(body);
console.log('Finished');
});
});
Changes to this, which works. Any comments?
function(url,callback){
request(url).on('data',(data) => {
try{
var json = JSON.parse(data);
}
catch(error){
callback("");
}
callback(json);
})
}
You can also use this. This is to async flow. The error comes when the response is not a JSON. Also in 404 status code .