Responding an image (via pipe and response.end()) leads into strange behaviour - javascript

I used this code to pipe an image to my clients:
req.pipe(fs.createReadStream(__dirname+'/imgen/cached_images/' + link).pipe(res))
it does work but sometimes the image is not transferred completely. But no error is thrown neither on client side (browser) nor on server side (node.js).
My second try was
var img = fs.readFileSync(__dirname+'/imgen/cached_images/' + link);
res.writeHead(200, {
'Content-Type' : 'image/png'
});
res.end(img, 'binary');
but it leads to the same strange behaviour...
Does anyone got a clue for me?
(abstracted code...)
var http = require('http');
http.createServer(function (req, res) {
Imgen.generateNew(
'virtualtwins/www_leonardocampus_de/overview/28',
'www.leonardocampus.de',
'overview',
'28',
null,
[],
[],
function (link) {
fs.stat(__dirname+'/imgen/cached_images/' + link, function(err, file_info) {
if (err) { console.log('err', err); }
console.log('file info', file_info.size);
res.writeHead(200, 'image/png');
fs.createReadStream(__dirname+'/imgen/cached_images/' + link).pipe(res);
});
}
);
}).listen(13337, '127.0.0.1');
Imgen.generateNew just creates a new file, saves it to the disk and gives back the path (link).

I've used this before and all that is needed is that in the function (req, res) {:
var path = ...;
res.writeHead(200, {
'Content-Type' : 'image/png'
});
fs.createReadStream(path).pipe(res);
where path is the computed path to the file to send. .pipe() will transfer the data from the read stream to the write stream and call end when the read stream ends, so there is no need to use res.end() after.

What the problem was: I had 2 different writeStreams! If WriteStream#1 is closed, the second should be closed too and then it all should be piped.
But node is asynchronous so while one has been closed, the other one hasn't. Even the stream.end() was called... well you always should wait for the close event!

Related

Sending file through HTTP request

I tried to receive the file and store it in the multer storage
Node js code
enter code here
app.post('/createLicence', upload.single('photo'),function(req, res ,next) {
// any logic goes here
console.log("filename" ,req.body.name)
if (!req.file) {
console.log("No file received");
return res.send({
success: false
});
} else {
console.log('file received');
var function_name = 'createLicence'
var arguments_array = [req.file.path,'Raghav','Mumbai','Approved']
invoke = require('/Users/sanjeev.natarajan/fabric-samples/fabcar/invoke.js');
invoke.invokechaincode(function_name,arguments_array)
return res.send({
success: true
})
}
});
but i am receiving no file is receivedi have send the request through postman
-
From : https://www.npmjs.com/package/multer
In order to use the multer package, you have first to define a few parameters so that it can work on your fileDirectory.
In your server.js :
let multer = require('multer');
let storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, '/path/to/storage/')
},
filename: function(req, file, callback) {
callback(null, file.originalname + '-' + Date.now());
}
});
let upload = multer({
storage: storage
});
Now, configure your route
router.route('/your/payload')
.post(authController.isAuthenticated, upload.any(), albumController.postFile)
Note that upload.any() will allow you to upload multiple different formatted files at once. Feel free to use any other kind of upload.method() depending on your needs.
From this point, multer already is doing its job, however you might want to keep track of the files uploaded on your server.
So, in your own module, the logic is pretty much straight forward :
(I'm assuming that you're using mongoose models since you're not giving much information, but that's not the relevant part anyway)
exports.postFile = async (req, res) => {
if (!req || !req.files || !req.files[0]) return res.status(400).send("Bad request.");
for (let i = 0; req.files[i]; i++) {
await File.create({
path: req.files[i],
originalName: req.files[i].originalName,
mimetype: req.files[i].mimetype,
owner: req.user.userId
}, (err, file) => {
if (err) console.log("Something went wrong: " + err); else {
// Do something with file
}
});
}
return res.status(418).send("I'm a teapot.");
}
This configuration and middleware use is ONLY for testing purpose, never ever let anyone upload something to your server without carefully handle that uploading process (file integrity, resource management, ...). An open uploading system can become a very wide backdoor getting straight to your server.
Hope this helps,
regards.

Retrieving metrics through librado using NodeJS

Good morning!
I'm having troubles trying to get a single number from librato to use in a html page.
I just want to get the last value of the metric AWS.Billing.EstimatedCharges.total, the name of the client that spent that value and put it all together in a HTML page (simple, but not to me)
I'm trying to use this API https://github.com/goodeggs/librato-node
And I still not figured out how to solve this problem.
ps: I cannot use the embed chart.
var http = require('http');
http.createServer(function (req, res) { }).listen(1337, "127.0.0.1");
console.log('Server running at 127.0.0.1:1337/');
var librato = require('librato-node');
api = librato.configure({email: 'myemail', token: 'mytoken'});
librato.start(); process.once('SIGINT', function() { librato.stop();
// stop optionally takes a callback });
// Don't forget to specify an error handler, otherwise errors will be thrown
librato.on('error', function(err) { console.error(err); });
Try npm install librato-metrics, there's a lot of guessing here so please report back }8*)
const client = require('librato-metrics').createClient(
{
email: process.env.LIBRATO_METRICS_EMAIL,
token: process.env.LIBRATO_METRICS_TOKEN
}
const payload = {
count: 1,
resolution: 60
};
client.get('/metrics/AWS.Billing.EstimatedCharges.total', payload,
function(err, response) {
if (err) {
console.error(err, payload);
} else {
console.log(response);
}
});
```

How do I write an image to buffer using native Node JS HTTP library?

I am really new to JavaScript and Node JS. I have various image URLs that I want to buffer. I have tried the request npm module but want a lower level library for what I want to achieve.
For example:
http://assets.loeildelaphotographie.com/uploads/article_photo/image/128456/_Santu_Mofokeng_-_TOWNSHIPS_Shebeen_Soweto_1987.jpg
I see lots of examples that suggest using the request module or examples that save files to disk. However, I cannot find an HTTP GET request example that simply buffers the image so I can pass to another function. It needs to have an "end" event so I upload the buffered image data with confidence in another step. Is there a sample pattern or "how to" on this someone could provide? Thanks!
This is the native way:
var http=require('http'), imageBuffer;
http.get(
'http://www.kame.net/img/kame-anime-small.gif',
function(res) {
var body=new Buffer(0);
if (res.statusCode!==200) {
return console.error('HTTP '+res.statusCode);
}
res.on('data', function(chunk) {
body=Buffer.concat([body, chunk]);
});
res.on('end', function() {
imageBuffer=body;
});
res.on('error', function(err) {
console.error(err);
});
}
);
// Small webserver serving the image at http://127.0.0.1:4567
http.createServer(function(req, res) {
res.write(imageBuffer || 'Please reload page');
res.end();
}).listen(4567, '127.0.0.1');
and using request (encoding:null for binary response):
var request=require('request'), imageBuffer;
request({
uri: 'http://www.kame.net/img/kame-anime-small.gif',
encoding: null
}, function(err, res, body) {
if (err) {
return console.error(err);
} else if (res.statusCode!==200) {
return console.error('HTTP '+res.statusCode);
}
imageBuffer=body;
});
// Small webserver serving the image at http://127.0.0.1:4567
require('http').createServer(function(req, res) {
res.write(imageBuffer || 'Please reload page');
res.end();
}).listen(4567, '127.0.0.1');
Here's a simple example using the built-in streaming that the http response has:
var http = require('http');
var fs = require('fs');
var file = fs.createWriteStream("test.png");
var request = http.get("some URL to an image", function(response) {
response.pipe(file);
});
I ran this myself and successfully downloaded an image from an external web site and saved it to a file and then loaded the file into the browser to see the same image.

How to serve (uploaded) images using Meteor

I have this Meteor application in which it is possible to upload images. The uploading parts seem to work. I store the images in .uploads. Now I would like to make these images accessable by the following URL
http://localhost:3000/uploads
After a bit of googling I was able to create the following server side code:
var fs = Meteor.require('fs');
if (Meteor.isServer) {
WebApp.connectHandlers.stack.splice(0, 0, {
route: '/uploads',
handle: function (req, res, next) {
var path = process.env.PWD + '/.' + req.originalUrl.substr(1);
fs.readFile(path, {encoding: 'binary'}, function (err,data) {
if (err) {
throw err;
}
res.writeHead(200, {
'Content-Type': 'image/png'
});
//res.setEncoding("binary"); // this method does not exist
res.write(data);
res.end();
});
}
});
}
This code works, the path constructed is correct and in the browser I receive the 200 code, except it cannot display the image. Something is wrong with the data the browser receives. I checked the image on disk which is fine. So the code above must do something wrong with the data. Any suggestions what that might be?
Here is the code I found after googling (and works for me) a few days ago when I wanted to do what you need to do
files are in .screenshots directory mapped to :
http://localhost:3000/screenshots
code :
//directly serve screenshot files from /.screenshots dir
var fs = Npm.require('fs');
WebApp.connectHandlers.use(function(req, res, next) {
var re = /^\/screenshots\/(.*)$/.exec(req.url);
if (re !== null) { // Only handle URLs that start with /screenshots/*
var filePath = process.env.PWD + '/.screenshots/' + re[1];
var data = fs.readFileSync(filePath, data);
res.writeHead(200, {
'Content-Type': 'image'
});
res.write(data);
res.end();
} else { // Other urls will have default behaviors
next();
}
});

Secure POST request from NodeJS to Node/Express hangs

I'm using the following to send POST data to a secure nodejs server:
File: main.js
var strdata = JSON.stringify({"data":"thisdata"});
var options = {
host: '192.168.1.63',
port: 3001,
path: '/saveconfig',
method: 'POST',
rejectUnauthorized: false,
requestCert: true,
agent: false,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(strdata)
}
};
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
console.log(req.write(strdata));
console.log(req.end());
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.on('finish', function() {
console.log("finished request");
});
In an otherwise functional expressjs server, these are the appropriate snippets:
File: app.js
app.post('/saveconfig', function() {
data.saveconfig; console.log("received request"); } );
app.get('/getconfig', data.getconfig);
File: data.js
exports.saveconfig = function(req, res) {
console.log("saveing config");
res.send(200);
res.end();
};
exports.getconfig = function(req, res) {
res.send("get OK");
}
With app.js running on the server (Ubuntu), I run main.js from the client (Windows 7). req.write and req.end execute and "finished request" logs to the console, but the request callback never fires.
On the server in app.js, the app.post event fires and logs "received request" to the console. But "saving config" never logs to the console. Only after I kill (^C) main.js, express then logs to the console "POST /saveconfig".
I know I'm missing something simple, but I've read dozens of coding examples and you can likely gather from my snippet, I've tried everything I can find or think of. I'd guess the request isn't finishing, but I don't know why. What is missing to get "exports.saveconfig" to fire?
additional information
The answer posted below fixed my problem. Because I'm new to stackoverflow, I can't post my own answer, but here's the rest of the story...
I appreciate your help. Being still new to JavaScript, I found I can learn a lot about an object by converting it to string. I was originally attempting to convert the req parameter to a string using a custom function. I just discovered it was apparently running into an endless loop after using JSON.stringify instead.
The code looked something like this:
exports.saveconfig = function (db) {
return function(req, res) {
console.log("saving config");
console.log(mymodule.serialize(req));
res.end("OK");
console.log(req.body);
};
};
I would have thought the above code should have logged the following to the console- even if the serialize method was in an endless loop:
POST /saveconfig
saving config
[nothing because of the endless loop]
Instead I got:
saving config
connections property is deprecated. Use getConnections() method
Being new to JavaScript, I assumed something was wrong with the request, the server, or some plumbing in-between. Of course, then the debugging code I added (along with my ignorance of JS) compounded the problem.
Changing
app.post('/saveconfig', function() {
data.saveconfig; console.log("received request"); } );
to
app.post('/saveconfig', datarts.saveconfig);
and removing the endless loop fixed the problem.
The problem is in you're app.js. You use data.saveConfig inside your callback without calling it. The right way would be
app.post('/saveconfig', function(req,res) {
data.saveconfig(req, res);
console.log("received request");
});
app.get('/getconfig', data.getconfig);
or (I assume the console.log is just for debugging purposes):
app.post('/saveconfig', data.saveconfig);
app.get('/getconfig', data.getconfig);
You could do your console.log() inside your data.saveconfig method if you want to go with the second example.

Categories