Cannot read property 'toString' of undefined node.js filesystem - node.js

I have this script here, upon loading the page, it should first load a header html boilerplate, some dynamic paragraphs, and end the request with a footer html boiler plate. Both Boilerplates come from external files.
After testing, I am receiving:
TypeError: Cannot read property 'toString' of undefined
at ReadFileContext.callback (/user_code/index.js:20:23)
at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:367:13)
My understanding was that I needed .toString() to ensure that what was loaded from the external files were buffered as strings.
exports.request = functions.https.onRequest((req, res) => {
fs.readFile('/public/templates/header-template.html', function(_err, data) {
res.write(data.toString());
console.log('Header Loaded');
});
res.writeHead(200, {'Content-Type': 'text/html'});
var q = url.parse(req.url, true).query;
var txt = '<p>Thanks <b>' + q.firstname + ' ' + q.lastname + '</b>. An email has been sent to <b>' + q.email + '</b> with details about your request.';
res.write(txt);
fs.readFile('/public/templates/footer-template.html', function(_err, data) {
res.end(data.toString());
console.log('Footer Loaded');
});
});
Any idea what I am doing wrong?

You should pass the encoding to toString() to convert from a Buffer.
data.toString('utf8');
Additionally, it seems your variable data is not defined, so perfhaps your file doesn't exists. Capture the error and see what's wrong:
if(_err){
console.error(_err);
}

Related

Downloading heavy images(>2GB) from server using NodeJS

I am using the AngularJS and NodeJS for my project. I am storing my images to the AWS-EFS storage which is attached with an AWS-EC2 instance. Everything is working fine till I was downloading small images(less than 1 GB). When I tried to download big images(greater than 1 GB) it is throwing error.
Here is my Back-end code,
getTiff: function(req, res)
{
res.set('Content-Type', 'application/octet-stream')
var name = req.param('filename').split('.')[0]
var id = req.param('id')
var filePath = '/mys3storage/' + id + '/' + name +
'/3_dsm_ortho/2_mosaic/' + name + '_transparent_mosaic_group1.tiff'
files = fs.readFileSync(filePath)
res.send(files)
},
error: Sending 500 ("Server Error") response:
RangeError: Invalid typed array length
at new Uint8Array (native)
at createBuffer (buffer.js:23:15)
at allocate (buffer.js:98:12)
at new Buffer (buffer.js:53:12)
at Object.fs.readFileSync (fs.js:419:16)
at Object.module.exports.getAutocad.res.getContourLines.res.getContourPdf.res.getOrthoM (G:\desktop\unifliBackend\api\controllers\WebController.js:153:20)
at wrapper (G:\desktop\unifliBackend\node_modules\#sailshq\lodash\lib\index.js:3250:19)
at routeTargetFnWrapper (G:\desktop\unifliBackend\node_modules\sails\lib\router\bind.js:181:5)
at callbacks (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:164:37)
at param (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:138:11)
at param (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:135:11)
at param (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:135:11)
at pass (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:145:5)
at nextRoute (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:100:7)
at callbacks (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:167:11)
at alwaysAllow (G:\desktop\unifliBackend\node_modules\sails\lib\hooks\policies\index.js:224:11)
at routeTargetFnWrapper (G:\desktop\unifliBackend\node_modules\sails\lib\router\bind.js:181:5)
at callbacks (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:164:37)
at param (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:138:11)
at param (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:135:11)
at param (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:135:11)
at pass (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:145:5)
at nextRoute (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:100:7)
at callbacks (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:167:11)
at G:\desktop\unifliBackend\node_modules\sails\lib\router\bind.js:232:18
at callbacks (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:164:37)
at param (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:138:11)
at pass (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:145:5)
at nextRoute (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:100:7)
at callbacks (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:167:11)
at G:\desktop\unifliBackend\node_modules\sails\lib\router\bind.js:232:18
at callbacks (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:164:37)
at param (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:138:11)
at pass (G:\desktop\unifliBackend\node_modules\#sailshq\express\lib\router\index.js:145:5)
I'have also tried with createReadStream() but I can download one file at a time, on second file it would give me network failed error on browser. Please help!
getTiff: function(req, res) {
res.set('Content-Type', 'application/octet-stream')
var name = req.param('filename').split('.')[0]
var filePath = req.param('id') var filePath = '/mys3storage/' + id + '/' + name + '/3_dsm_ortho/2_mosaic/' + name + '_transparent_mosaic_group1.tiff'
fs.createReadStream(filePath).pipe(res)
}
This is the stream code I have used. It is working fine when I download one file at a time. if try to download to two files at a time it will stop the second file and shows "network failed" from browser
Here is my browser side code:
$scope.downloadOrthoMission = function(idForDownload, missionIdForDownload) {
window.open(adminurl + 'getTiff/' + idForDownload + '/' + missionIdForDownload + '.tif', '_self')
}
Just referred this answer,
Nginx node.js express download big files stop at 1.08GB
It is working absolutely fine for me.

Simple nodejs example with multiple files

I wrote very simple project on NodeJS. I want to make similarity to other language programming example, such as java. So I make: server.js, main.js and module (calc.js). Here are their code:
File server.js
var main = require('./main');
var http = require('http');
http.createServer(function(req, res){
main.main(req, res);
}).listen(8080, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8080/');
File main.js
var calc = require('./calc');
exports.main = function(req, res){
var a = 5;
var b = 9;
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(calc.Plus(a,b));
res.end(calc.Minus(a,b));
};
File calc.js
(function(){
module.exports.Plus = function(a, b){
return a+b;
};
module.exports.Minus = function(a, b){
return a-b;
};
}());
I run it on my server, and I got an error:
Server running at http://127.0.0.1:8080/
_http_outgoing.js:558
throw new TypeError('First argument must be a string or Buffer');
^
TypeError: First argument must be a string or Buffer
at ServerResponse.OutgoingMessage.end (_http_outgoing.js:558:11)
at Object.exports.main (D:\workspace\FirstNodeJS\main.js:7:6)
at Server. (D:\workspace\FirstNodeJS\server.js:5:7)
at emitTwo (events.js:106:13)
at Server.emit (events.js:191:7)
at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:546:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
I am just a newbie with NodeJS.
res.end() expects the first argument to be a string or a buffer. You are passing a number. That is how it is described in the doc here.
You could do:
res.end(calc.Plus(a,b).toString());
Also, you can only call res.end() once for a given response. If you want to send multiple things as part of the response, you can either combine them all into a string before using res.end() or you can call res.write() multiple times and then finish it with res.end().
There are 2 issues to your problem.
First problem is that the `.write(...) API from NodeJS's response object takes in a string buffer or string.
Quote:
response.write(chunk[, encoding][, callback])
chunk < string > | < Buffer >
encoding
callback Returns:
See: https://nodejs.org/api/http.html#http_response_write_chunk_encoding_callback
Your calculation methods Plus and Minus are returning Integer. Hence you need to convert the Numbers to String before writting;
Example:
var calc = require('./calc');
exports.main = function(req, res){
var a = 5;
var b = 9;
res.writeHead(200, {'Content-Type': 'text/plain'});
var result = calc.Plus(a,b);
res.write(result.toString());
res.write("\n");
result = calc.Minus(a,b);
res.write(result.toString());
res.end();
};
Also, problem number 2 is that you should only call .end(...) once for each response object.
You should either build your result and then call it. Or call .write(...) as many times as you need and when you are happy then close the communication by calling .end(...).
Another thing, you might want to line break \n your results so that the output looks like;
If not it will be a one liner, 14-4.

pipe file directly from file system

I'm using "express": "^4.13.3" on node 6.9.0
When i try to pipe data a jpeg image:
const path = config.storageRoot + '/' + req.params.originalFileName;
var mimetype = mime.lookup(req.params.originalFileName);
res.writeHead(200, { 'Content-Type': mimetype});
fs.createReadStream(path).pipe(res);
i get xml data inside the result:
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.5-c014 79.151739, 2013/04/03-12:12:15 ">
When i use res.end with the result from a fs.readFile instead, the binary content is formatted correctly.
What am i doing wrong?
Take a look how I'm piping files in the examples in this answer:
How to serve an image using nodejs
It's something like this:
// 'type' is the MIME type
var s = fs.createReadStream(file);
s.on('open', function () {
res.set('Content-Type', type);
s.pipe(res);
});
s.on('error', function () {
res.set('Content-Type', 'text/plain');
res.status(404).end('Not found');
});
So I'm just setting the header to be posted by Express instead of posting the headers explicitly. Also I'm handling the stream events. Maybe you should try doing it similarly because the way I did it seems to work, according to Travis:
https://travis-ci.org/rsp/node-static-http-servers
Another thing in addition to handling the stream events and errors would be to make sure that you have the correct encoding, permissions etc. I don't know what result are you expecting and what that XML means or where it comes from, but handling the stream events may tell you more about what is happening.

How to pipe image from request to pdfkit in node.js?

First off, I am a total newbie both to Javascript and Node.js, so sorry if my question is stupid.
I am trying to scrape text and images off a website and export it to a pdf using request, cheerio and pdfkit, but I'm having problems.
I am able to scrape the images and save them locally using this:
var $ = cheerio.load(body);
$("#mediatab1 img").each(function(){
var image= 'http://WWW.WEBSITE.no' + $(this).attr('src');
images.push(image);
});
for(var i = 0; i < images.length; i++){
request(images[i]).pipe(fs.createWriteStream('images/' + i + '.jpg')); }
BUT! Here's the problem:
1. INTENT: When I try to write the files to the pdf using
doc.image('images/0.jpg');
all I get is
Error: Unknown image format.
at Function.PDFImage.open (C:\nodejs\node_modules\pdfkit\js\im
age.js:41:15)
at PDFDocument.module.exports.image (C:\nodejs\node_modules\pd
fkit\js\mixins\images.js:27:26)
at Request._callback (C:\nodejs\prosjekt.js:29:6)
at Request.self.callback (C:\nodejs\node_modules\request\reque
st.js:344:22)
at Request.emit (events.js:98:17)
at Request.<anonymous> (C:\nodejs\node_modules\request\request
.js:1239:14)
at Request.emit (events.js:117:20)
at IncomingMessage.<anonymous> (C:\nodejs\node_modules\request
\request.js:1187:12)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:944:16
0.jpg is 0 bytes, so I suspect there is a timing issue here?
2. INTENT
I tried to use .pipe instead of saving locally:
request(images[i]).pipe(doc.image(images[0]));
But all I get is:
"Error: ENOENT, no such file or directory 'C:\nodejs\http:\www.WEBSITE.no\Common\Tools\ImageScaler.ashx?id=c7d73548-8198-4bd1-867d-33fc0dfe73d1&h=4
13'
Any idea how to fix this or to solve the problem in any other way?
Here's the whole script:
var request = require('request'),
cheerio = require('cheerio'),
PDFDocument = require('pdfkit'),
doc = new PDFDocument,
fs = require('fs'),
prompt = require('prompt');
bilder = [];
prompt.start();
prompt.get(['prosjekturl'], function (err, result) {
request({url: 'http://www.WEBSITE.no/no/Prosjekter/Prosjekt/?pid=' + result.prosjekturl, encoding:null}, function(err, resp, body){
if(!err && resp.statusCode == 200){
// console.log(body);
var $ = cheerio.load(body);
$("#mediatab1 img").each(function(){
var bilde = 'http://www.WEBSITE.no' + $(this).attr('src');
bilder.push(bilde);
});
console.log(bilder);
for(var i = 0; i < bilder.length; i++){
request(bilder[i]).pipe(fs.createWriteStream('images/' + i + '.jpg'));
}
$("#MiddleRightContainer h1").each(function(){
var tittel = $(this).text();
console.log(tittel);
doc.pipe(fs.createWriteStream('pdf/output.pdf'));
doc.font('fonts/FONT-Regular.ttf');
doc.fontSize(32);
doc.text(tittel);
});
$("#MiddleRightContainer .user-content p").each(function(){
var tekst = $(this).text();
console.log(tekst);
doc.pipe(fs.createWriteStream('pdf/output.pdf'));
doc.fontSize(12);
doc.text(tekst);
});
$("#RightSidebar div.box2").each(function(){
var fakta = $(this).text();
console.log(fakta);
});
}
doc.end();
});
});
From docs:
"PDFKit supports the JPEG and PNG formats"
Here you can see it's checking .jpeg and .png extensions. Yours is a .jpg file. I've had trouble with this a few times and this has fixed my issue.
When it comes to the file loading I suspect that the windows paths can be a problem. Try and use node.js built-in path resolution: https://nodejs.org/api/path.html
When it comes to request and loading images it should not be more than:
request({
url: url,
// Prevents Request from converting response to string
encoding: null
}, function (err, response, body) {
doc.image(body)
})
Hope it helps some.

Making an HTTP request using node.js throws EAFNOSUPPORT

I'm trying to make a simple HTTP GET request using node.js, but I'm running into trouble using node.js v0.3.4-pre (i.e. compiled from HEAD as of this morning). Here's my code:
var cli = require('cli');
var http = require('http');
var url = require('url');
cli.parse();
cli.main(function(args, opts) {
this.debug(args[0]);
var siteUrl = url.parse(args[0]);
var site = http.createClient(siteUrl.port, siteUrl.host);
console.log(siteUrl);
var request = site.request("GET", siteUrl.pathname, {'host' : siteUrl.host})
request.end();
request.on('response', function(response) {
response.setEncoding('utf8');
console.log('STATUS: ' + response.statusCode);
response.on('data', function(chunk) {
console.log("DATA: " + chunk);
});
});
});
Here's the error that I get:
node.js:68
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: EAFNOSUPPORT, Address family not supported by protocol family
at doConnect (net.js:499:19)
at Client.connect (net.js:652:30)
at Client._ensureConnection (http.js:1033:10)
at Client.request (http.js:1048:8)
at Object.<anonymous> (/Users/paul/Desktop/readify.js:16:21)
at /usr/local/lib/node/.npm/cli/0.2.3-2/package/cli.js:995:18
at Object.main (/usr/local/lib/node/.npm/cli/0.2.3-2/package/cli.js:1000:9)
at Object.<anonymous> (/Users/paul/Desktop/readify.js:10:5)
at Module._compile (node.js:359:32)
at Object..js (node.js:367:14)
Found the bug, siteUrl.port will be undefined unless the URL explicitly names a port. So, the solution is:
var site = http.createClient(siteUrl.port || 80, siteUrl.host);
var site = http.createClient(siteUrl.port, siteUrl.host);
should rather be
var site = http.createClient(siteUrl.port || 80, siteUrl.hostname);
The same error message appeared on my very old XPSP2-box for ANY connect()-attempts. E.g npm wasn't able to do anything, and simple http requests failed.
While trying to find a solution, this post appeared all over the place, but its not the same issue.
In my case it had to do with WSAIoctl(...) always returning WSAEOPNOTSUPP when querying for WSAID_CONNECTEX, which seemed strange. This led me to a post recommending doing a "netsh winsock reset" from the cmd, which fixed the problem!

Resources