Receiving POST request with node.js - javascript

I have an Axis M1011 camera which is set up to send a series of jpeg images as long as it is detecting motion, to a service (using HTTP POST). I'm building the service using node.js.
I'm successfully receiving POST requests with their headers, but I am having trouble saving the data in the body of the request. Here is the code:
function addEvent(req, res)
{
var buffer = '';
console.log(req.headers);
req.on("data", function(chunk)
{
console.log("chunk received");
buffer += chunk;
});
req.on("end", function()
{
console.log("saving file");
fs.writeFile("./tmp/"+ new Date().getTime()+".jpg", buffer, function(error)
{
if(error)
{
console.log(error);
}
else
{
console.log("saved");
res.send("OK");
res.end();
}
});
});
}
On the console, I get this kind of output. Ofcourse, the content-length differs from file to file:
{ host: '192.168.0.100:8888',
'content-type': 'image/jpeg',
'content-disposition': 'attachment; filename="file13-07-19_20-49-44-91"',
'content-length': '18978' }
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
chunk received
saving file
saved
The problem is that I am getting one same, corrupted, file in the tmp folder which size is about 33KB, no matter how big is the image. What am I doing wrong with receiving these files?

You need to process the POST request to get the file that has been sent. When you submit a file in POST request, you wrap file meta data as well as data and send it to the server.
The server has to decode the request, and get the file. Simply saving the request won't do. You did not mention if you are using any web-server framework. It is better you use one like express which does this for you. Express will parse the request, get the file object and save the file into temporary file.

Related

AJAX request png/jpeg image from (NodeJS + Express) server and show it in html

basically I need to receive png or jpeg image from my server, and show it inside img tag on my website.
My architecture looks like this:
Client - Server1 (my server) - Server2 (some public server)
Client sends Ajax request to Server1.
Server1 sends request to Server2.
Server2 sends image back to Server1.
Server1 sends image back to Client.
Client code:
$("#testButton").click(function() {
$.ajax({
method: "get",
async: false,
url: "/test"
}).done(function (response){
alert(response.imageData);
$("#resultImage").attr("src", "data:image/png;base64," + response.imageData);
});
});
Server1 code:
router.get('/test', function(req, res, next){
var url = 'https://ion.gemma.feri.um.si/ion/services/geoserver/demo1/wms?service=WMS&version=1.1.0&request=GetMap&layers=demo1%3Amaribor-dof25&bbox=546631.6237364038%2C156484.86830455417%2C550631.7865026393%2C160485.0310707898&width=767&height=768&srs=EPSG%3A3794&format=image%2Fjpeg';
request(url, function (error, response, body) {
console.log('error:', error);
console.log('statusCode:', response && response.statusCode);
console.log(response.headers['content-type']);
console.log(body);
return res.json({ imageData: body});
});
});
If I enter the url above directly to img src, it is shown correctly.
Image is also shown correctly when I input url directly into browser.
When I receive image data back to my client from server1, data looks like this:
Any ideas how to fix this ?
Since you're building a base64 encoded image on the front end, the backend must return a base64 encoded image.
You are returning the image in utf8 format which of course won't work. utf8 is the default encoding when using request package.
You can use encoding property of the request package for that. Or pass encoding: null & convert body to a base64 string using .toString('base64')
request({ url, encoding: 'base64' }, function (error, response, body) {
console.log('error:', error);
console.log('statusCode:', response && response.statusCode);
console.log(response.headers['content-type']);
console.log(body);
return res.json({ imageData: body});
});
Now response.imageData is a base64 encoded string that you can use with: data:image/png;base64,
Have in mind that you're harcoding png on the front end. If you're going to work with different extensions, you can send the full src from the server:
// 'content-type' must not be image/png or image/jpeg, improve the logic
// I'll leave that to you.
const src = `data:${response.headers['content-type']};base64,${body}`;
return res.json({ src });
Another option, is to remove the ajax, and send the image directly, without base64.
front
$("#resultImage").attr("src", "/test");
back
app.get('/test', (req, res) => {
let url = 'https://ion.gemma.feri.um.si/ion/services/geoserver/demo1/wms?service=WMS&version=1.1.0&request=GetMap&layers=demo1%3Amaribor-dof25&bbox=546631.6237364038%2C156484.86830455417%2C550631.7865026393%2C160485.0310707898&width=767&height=768&srs=EPSG%3A3794&format=image%2Fjpeg';
request(url).pipe(res);
});

How to save an incoming filestream from Node into AngularJS

On my express server I have a post-request which is getting a pdf file from Amazon S3 and sending it back to angular. This is how my express server endpoint ends with:
var fileStream = s3.getObject(options).createReadStream();
fileStream.pipe(res);
On the angular side of things I am posting and trying to save this
$http.post(url, data)
.then(function (data, status, headers, config) {
var file = new Blob([data.data], {type: 'application/pdf'});
FileSaver.saveAs(file, vm.projectName);
})
I get a pdf file which is not valid. I has about 300kb (more than original file) and I believe its not pdf but a buffer?
What I am trying to achieve:
- Post Request to server
- Server gets file from S3, Sends it back to Angular Controller
- Angular Controller saves it as .png
When you're making POST call, set responseType of request to arrayBuffer inside configuration, so that response will get transformed to correctly.
$http.post(url, data, {responseType: "arraybuffer"})

How to save zip file represented as a string in Node js

I have a response from an ebay-api
--MIMEBoundaryurn_uuid_C91296EA5FF69EE9571479882375576565344 Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Content-Transfer-Encoding: binary Content-ID:
<0.urn:uuid:C91296EA5FF69EE9571479882375576565345>
Success1.1.02016-11-23T06:26:15.576Z514
--MIMEBoundaryurn_uuid_C91296EA5FF69EE9571479882375574545344 Content-Type: application/zip Content-Transfer-Encoding: binary
Content-ID:
PKY'uIi[��#�50014028337_report.xmlUT y�2Xy�2Xux
00�R�j�#��+��[��PlX#�(�x,=l�q]Lfewc��w Ĥ��O��١�HT���t��GGT�
��6�;���'������.$����=d����m;c}Wߦ�RW�A
f�����g�I��4U��x��3��f���ғ{f��xj�,+���ۖI%5��B's��G,#��t,L{�c�����MD笓��)!�9��
�M�o;8_��<�i�y����sz���u���=��Ջ^2�S��%+2�2�`QV�$�����~?�w�ǥ�_Q�퉦�'PKY'uIi[��#���50014028337_report.xmlUTy�2Xux
00PK\�
--MIMEBoundaryurn_uuid_C91296EA5FF69EE9571479882375576565344--
This is of type string. and i extracted the attached zip file data i.e.
PKY'uIi[��#�50014028337_report.xmlUT y�2Xy�2Xux
00�R�j�#��+��[��PlX#�(�x,=l�q]Lfewc��w Ĥ��O��١�HT���t��GGT�
��6�;���'������.$����=d����m;c}Wߦ�RW�A
f�����g�I��4U��x��3��f���ғ{f��xj�,+���ۖI%5��B's��G,#��t,L{�c�����MD笓��)!�9��
�M�o;8_��<�i�y����sz���u���=��Ջ^2�S��%+2�2�`QV�$�����~?�w�ǥ�_Q�퉦�'PKY'uIi[��#���50014028338_report.xmlUTy�2Xux
00PK\�
This shows that it has a report.xml in it. So when i write this data in a zip file, it creates a zip file and upon extract gives error.
fs.writeFile("./static/DownloadFile.zip", fileData, 'binary', function(err){
if (err) throw err;
console.log("success");
});
How can i write this data in a zip file properly. Pls advice. If required any more information.
EDIT:
I tried writing the zip file in PHP and is succssfully writing it with this code:
$zipFilename="DownloadFile.zip";
$data = $fileData;
$handler = fopen($zipFilename, 'wb')
or die("Failed. Cannot Open $zipFilename to Write!</b></p>");
fwrite($handler, $data);
fclose($handler);
Please advice how can i achieve the same thing in nodejs.
Depending on what HTTP Client you are using the implementation might change a little.
With axios I'm doing something like so:
I'm requesting a zip file so I specify the Accept header as application/zip
In order to get a buffer and not Binary, specify the responseType as arrayBuffer
const res = await axios.get('/routToThat/file', {
headers: {
Accept: 'application/zip',
},
responseType: 'arraybuffer',
});
By doing the latter, instead of receiving a Binary from the response:
A#B�ArE⏾�7�ϫ���f�걺N�����Yg���o_M^�D�T�U X_���e?� hi\...
I receive a Buffer:
Buffer(22781691) [80, 75, 3, …]
Once the request is resolved and I have that Buffer, I use that same writeFile function from fs
NOTE: I'm not specifying the Encoding in writeFile
fs.writeFile(name, res.data, (err) => {
if (err) throw err;
console.log("success");
});
As I see in your code example your binary data is already mangled by request module. Just use in request setting
encoding:null
and the zip file is a valid binary in body (now buffer instead of utf-8 string!) you can decompress. As long as you see the questions marks you still have the encoding issue.

Sending two objects as response to a single GET request using Express and Node.js

I have the following piece of code -
sendServer.get('/download',function(request,response){
var status="SELECT * from poetserver.download where status='0'";
console.log(status)
connection.query(status,function(error,rows){
var toSend=rows[0].id
response.sendfile('./testimages/'+toSend+'.PNG')
// var details={"pictureId":toSend}
// response.writeHead(200, { 'Content-Type': 'application/json' });
// response.send(JSON.stringify(details));
Essentially I, first, want to send a file as identified by toSend. The file is successfully sent using response.sendFile. But I also want to provide some identification of the file for the client for future responses. How do I send that too?
To send an id for the image (ressource) that you are responding with, you should use a HTTP header such as ETag. Do not try to send JSON and binary data in one response body.

Node js - How to serve multiple SVG files to a browser

I'm new to Node and server oriented code and am trying to get multiple svg files which are stored in the server.
Here is my code client-side using jQuery:
$.ajax({
url: someURL,
data: someData
})
.done(function(data) {
console.log('data got', data);
callback(null, data);
})
.fail(function() {
callback(new Error('Cannot access files'));
});
And here is my code server side:
// links is an array of links to the different svg files
var svgs = [];
async.eachSeries(links, function(link, next) {
fs.readFile(link, function(err, svg) {
svgs.push(svg);
next(err);
});
}, function(err) {
if (err) {
response.writeHead(500);
response.end(JSON.stringify(err));
return;
}
response.writeHead(200);
response.end(svgs); // Doesn't work
// response.end(svgs[0]); // Works
});
As long as I send only one file to the browser (which seem to be a Buffer instance), everything seems to work fine, but when I try to send multiple ones as an Array the transaction succeed but I got nothing in my returned data. That may be related to the MIME type of what I'm trying to send, but I couldn't find how to handle that.
You'll have to convert svgs into a String or Buffer first. One option is to stringify it as JSON:
response.writeHead(200, {
'Content-Type': 'application/json'
});
response.end(JSON.stringify(svgs));
This is because response.write(), which response.end() is calling to handle the data (svgs), doesn't accept Arrays.
chunk can be a string or a buffer. If chunk is a string, the second parameter specifies how to encode it into a byte stream. By default the encoding is 'utf8'.
Whereas each svg provided by fs.readFile() is a Buffer, so it has no issues writing svgs[0].

Categories

Resources