REST API call works only once - javascript

I have written a Nodejs REST API application with a number of functions. However when I consume one of the APIs it returns me the excel file it is supposed to return and everything is fine until there. After that the application stops responding and all the other functions stop working. The cde for the problematic function is following:
app.get('/api/Export', function (req, res) {
UsageData.aggregate([{
$match: {
$and: [{
GroupName: {
$ne: "Group1"
}
}, {
GroupName: {
$ne: "Group2"
}
}]
}
}
, {
$group: {
_id: '$ToolType'
, count: {
$sum: 1
}
}
}]
, function (err, usagedata) {
usagedata = getJSON(usagedata);
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err)
var wb = new xl.WorkBook();
var ws = wb.WorkSheet('Usage');
ws.Column(2).Width(35);
var headercell1 = ws.Cell(2, 2);
headercell1.String('Tool');
var headercell2 = ws.Cell(2, 3);
headercell2.String('Usage');
var myStyle = wb.Style();
myStyle.Font.Bold();
myStyle.Fill.Color('#CCCCCC');
myStyle.Border({
top: {
style: 'thick'
, color: '000000'
}
, right: {
style: 'thick'
, color: '000000'
}
, bottom: {
style: 'thick'
, color: '000000'
}
, left: {
style: 'thick'
, color: '000000'
}
});
myStyle.Font.Alignment.Horizontal('center');
var borderstyle = wb.Style();
borderstyle.Border({
top: {
style: 'thin'
, color: '000000'
}
, right: {
style: 'thin'
, color: '000000'
}
, bottom: {
style: 'thin'
, color: '000000'
}
, left: {
style: 'thin'
, color: '000000'
}
});
borderstyle.Font.Alignment.Horizontal('center');
headercell1.Style(myStyle);
headercell2.Style(myStyle);
for (var i = 0; i < usagedata.length; i++) {
var cell = ws.Cell(2 + i + 1, 2);
cell.String(usagedata[i].Tool);
cell.Style(borderstyle);
var cell1 = ws.Cell(2 + i + 1, 3);
cell1.Number(usagedata[i].Count);
cell1.Style(borderstyle);
}
UsageData.aggregate([{
$match: {
$and: [{
GroupName: {
$ne: ""
}
}, {
GroupName: {
$ne: "Group1"
}
}, {
GroupName: {
$ne: "Group2"
}
}]
}
}
, {
$group: {
_id: '$GroupName'
, count: {
$sum: 1
}
}
}]
, function (err, data) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err)
var wsg = wb.WorkSheet("Group Usage");
wsg.Column(2).Width(35);
var headercell = wsg.Cell(2, 2);
headercell.String('Group');
headercell.Style(myStyle);
var headercell = wsg.Cell(2, 3);
headercell.String('Usage');
headercell.Style(myStyle);
for (var i = 0; i < data.length; i++) {
var cell = wsg.Cell(2 + i + 1, 2);
cell.String(data[i]._id);
cell.Style(borderstyle);
var cell1 = wsg.Cell(2 + i + 1, 3);
cell1.Number(data[i].count);
cell1.Style(borderstyle);
}
wb.write('Report.xlsx', res);
var filename = "Report.xlsx";
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.pipe(res);
});
return;
});
return;
});
I am using Node4Excel to generate an excel file from the data I get from my Mongodb. The API returns the excel file for the first time. Second time onwards, it doesnt return anything and neither does the other APIs. Please help.

I finally fixed it by using the following lines:
wb.write('Report.xlsx', res,function(){
var filename = "Report.xlsx";
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.pipe(res);
});

Related

Discord.js Source server query

I'm trying to make a Discord.js bot that will get data from the CS:GO server and shows it in embed that will be edited and updated (for example every 2 minutes). I still have some problems with the code, currently I stuck with the error "TypeError: Cannot read property 'edit' of undefined"
const Discord = require("discord.js");
var SourceQuery = require('sourcequery');
const client = new Discord.Client();
const config = require("./config.json");
client.on("ready", () => {
console.log(`bot is ready`);
});
client.on("ready", (message, embed) => {
function queryserver(ip, port, sendChannel) {
let sq = new SourceQuery(1000);
console.log(ip + " " + port);
sq.open(ip, port);
sq.getInfo(function (err, info) {
if (!err) {
sq.getPlayers(function (err, players) {
if (!err) {
console.log(sq.address);
var counter = 0;
playersname = "";
for (i = 0; i < players.length; i++) {
playersname = playersname + players[i].name + "\n";
if (counter == players.length - 1) {
client.channels.cache.get(sendChannel).send({
embed: {
color: 3066993,
fields: [{
name: "Server name",
value: "**" + info.name + "**"
},
{
name: "IP",
value: ip + ":" + port,
"inline": true
},
{
name: "Mapa",
value: info.map,
"inline": true
},
{
name: "Max slots",
value: info.maxplayers,
"inline": true
},
{
name: "Online",
value: info.players,
"inline": true
},
{
name: "Player list",
value: "```" + playersname + "```"
}
],
timestamp: new Date(),
footer: {
icon_url: client.user.avatarURL,
text: "Last update:"
}
}
});
}
counter++;
}
}
else {
console.log("Error...");
message.channel.send("Error...");
}
});
}
else {
console.log("Error...");
message.channel.send("Error...");
}
});
};
setInterval(function() {
queryserver(`216.52.148.47`, `27015`, `834355545879347233`);
message.edit(embed)
}, 2000);
});
client.login(config.token);
Can anyone help me?

Extract Font Name from PDF

I am using pdf.js to extract text from the pdf but the font name appears as g_d0_f6 etc. I need the font name to use the appropriate table for converting to Unicode. Here is the code derived from pdf2svg.js sample:-
var fs = require('fs');
var util = require('util');
var path = require('path');
var stream = require('stream');
// HACK few hacks to let PDF.js be loaded not as a module in global space.
require('./domstubs.js').setStubs(global);
var pdfjsLib = require('pdfjs-dist');
var pdfPath = process.argv[2] || '../../web/compressed.tracemonkey-pldi-09.pdf';
var data = new Uint8Array(fs.readFileSync(pdfPath));
var loadingTask = pdfjsLib.getDocument({
data: data,
nativeImageDecoderSupport: pdfjsLib.NativeImageDecoding.DISPLAY,
});
loadingTask.promise.then(function(doc) {
var lastPromise = Promise.resolve(); // will be used to chain promises
var loadPage = function (pageNum) {
return doc.getPage(pageNum).then(function (page) {
return page.getTextContent().then(function (textContent) {
console.log(textContent);
});
});
};
for (var i = 1; i <= doc.numPages; i++) {
lastPromise = lastPromise.then(loadPage.bind(null, i));
}
return lastPromise;
}).then(function () {
console.log('# End of Document');
}, function (err) {
console.error('Error: ' + err);
});
Sample output:-
{ items:
[ { str: 'bl fp=k osQ ckjs esa cPpksa ls ckrphr djsa & ;g LowQy esa fdl le; dk n`\'; gS\\ cPps',
dir: 'ltr',
width: 396.2250000000001,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'D;k dj jgs gSa\\ cPps dkSu&dkSu ls [ksy] [ksy j',
dir: 'ltr',
width: 216.1650000000001,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'g',
dir: 'ltr',
width: 6.42,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 's gSa\\ fp=k esa fdrus cPps gSa vkSj fdrus',
dir: 'ltr',
width: 173.865,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'cM+s gSa\\ vkil esa dkSu D;k ckr dj jgk gksxk\\ cPpksa ls fp=k esa lcosQ fy, uke lkspus',
dir: 'ltr',
width: 396.54000000000013,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'dks dgasaA',
dir: 'ltr',
width: 40.74,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'csVh cpkvks',
dir: 'ltr',
width: 66.725,
height: 17,
transform: [Array],
fontName: 'g_d0_f2' },
{ str: 'csVh i<+kvksA',
dir: 'ltr',
width: 66.75899999999999,
height: 17,
transform: [Array],
fontName: 'g_d0_f2' },
{ str: '2018-19',
dir: 'ltr',
width: 36.690000000000005,
height: 10,
transform: [Array],
fontName: 'g_d0_f3' } ],
styles:
{ g_d0_f1:
{ fontFamily: 'sans-serif',
ascent: 0.837,
descent: -0.216,
vertical: false },
g_d0_f2:
{ fontFamily: 'sans-serif',
ascent: 0.786,
descent: -0.181,
vertical: false },
g_d0_f3:
{ fontFamily: 'sans-serif',
ascent: 0.9052734375,
descent: -0.2119140625,
vertical: false } } }
And here is the pdf that uses embedded fonts: http://ncert.nic.in/textbook/pdf/ahhn101.pdf
Here is a related question but the suggested commonObjs is empty: pdf.js get info about embedded fonts
Note: The answer below does not have anything to do with pdf.js, however it answers the question, Extract Font Name from PDF.
I did not find a solution yet, so I went ahead and grabbed mutool, which has has the following command to get the font information per page.
mutool info -F input.pdf 0-2147483647
Then I grabbed the spawn function, hacked the output through some regex and pattern matching to return the data.
const extractFontData = async str => {
const getMatches = str => {
const regex = /Page (\d+):\nFonts \((\d+)\):/;
const match = str.match(regex);
if (match) {
return { page: match[1], fonts: match[2] };
}
return {};
};
const singleFont = fontData => {
const match = fontData.match(/\+([a-zA-Z0-9_-]+[.,]?[a-zA-Z0-9_-]+)/);
return match && match[1];
};
return str
.split("Page ")
.map(singlePageData => {
const { page, fonts } = getMatches(`Page ` + singlePageData);
if (fonts) {
const split = singlePageData.split("\n").filter(e => e.length);
const fontList = split.slice(2).map(singleFont);
return { page, fonts, fontList };
}
})
.filter(e => e);
};
// Taken and adjusted from: https://stackoverflow.com/a/52611536/6161265
function run(...cmd) {
return new Promise((resolve, reject) => {
var { spawn } = require("child_process");
var command = spawn(...cmd);
var result = "";
command.stdout.on("data", function(data) {
result += data.toString();
});
command.on("close", function(code) {
resolve(result);
});
command.on("error", function(err) {
reject(err);
});
});
}
async function wrapper(filePath) {
const data = await run("mutool", ["info", "-F", filePath, "0-2147483647"]);
return extractFontData(data);
}
Sample usage:
wrapper("ahhn101.pdf").then(data => console.log(data));
Result:
I think you were on the right track: page.commonObjs is where the actual font name is found. However, page.commonObjs only gets populated when the page's text/operators are accessed, so you'll find it empty if you look before that happens.

node js - multi tasking for each item in array

I am trying to implement a way to upload files asynchronously.
I have a process I want to apply to every item of my array.
I am taking the name of each item, call a API to get additinal information about it, then I am sending it to a text to speech utility, and upload the resultingwav file to a S3 instance.
I can't find a way to do this asynchronously, and wait for all of them to finish.
I can do it in serie, but it take lots of time (12 minutes for 30 files (2mb each file)).
I tried to implement a asynchronous way, which takes around 5 minutes (7 minutes less), but I fear the problem is on the net line?
Function to apply to each item:
function doAll(c, lan, country, fileName, callback){
getNews(c, lan)
.then(function(newsResults){
getWavFile(newsResults, lan, fileName)
.then(function(wavResults){
uploadToS3(country,lan,fileName)
.then(function(s3Results){
return callback("done");
}, function(s3err){
console.log('s3 error: ',s3err);
return callback("done");
})
}, function(waverr){
console.log('wav error: ',waverr);
})
}, function(newserr){
console.log('news error: ',newserr);
})
}
Array example :
var arr = [
{
_id: '5769369ba2d42fd82ca4d851',
Name: 'Sports',
Order: 1,
Color: 'White',
Description: 'ספורט',
UpdatedDate: '2016-07-28T07:44:47.906Z',
CreatedDate: '2016-06-21T12:44:11.468Z',
Country: 'IL',
Langs: [
{
Name: 'Sports',
IsoCode: 'en',
Url: 'SportsJSON',
_id: '576b93486c7a9ff025275836'
},
{
Name: 'ספורט',
IsoCode: 'iw',
Url: 'HebrewSportsJSON',
_id: '576be6ad56126ccc25852613'
}
]
},
{
_id: '576bf4eb28176a3e5ce15afa',
Name: 'Top Stories',
Description: 'הכותרות',
Color: 'ww',
Order: 1,
UpdatedDate: '2016-07-10T12:01:26.713Z',
CreatedDate: '2016-06-23T14:40:43.435Z',
Country: 'IL',
Langs: [
{
Name: 'כותרות',
Url: 'HebrewTopStoriesJSON',
IsoCode: 'iw',
_id: '576bf52228176a3e5ce15afb'
},
{
Name: 'Top Stories',
IsoCode: 'en',
Url: 'TopStoriesJSON',
_id: '576bf94d28176a3e5ce15afd'
}
]
},
{
_id: '5756d5d6c4a3dfe478b16aa2',
Description: 'Nation Channel',
Order: 1,
Color: 'blue',
Code: 'Nation',
Name: 'Nation',
UpdatedDate: '2016-06-24T22:23:07.198Z',
CreatedDate: '2016-06-07T14:10:30.699Z',
Country: 'US',
Langs: [
{
Name: 'Nation',
IsoCode: 'en',
Url: 'NationJson',
_id: '576db2cb28176a3e5ce15b02'
}
]
}
]
My asynchronous way:
var array = [] // see the example how array look like
var newArray= [];
console.log('start uploading files time:', new Date());
for (var i = 0; i < array.length; i++) {
var list = array[i].Langs;
for (var j= 0; j < list.length; j++) {
var c = list[j];
var lan = convertIsoCode(c.IsoCode);
var fileName = array[i].Name + "_" + lan;
var country = array[i].Country;
doAll(c,lan,country,fileName, function(){
newArray.push(array[i]);
if (array.length == newArray.length) {
console.log('done');
defer.resolve('done');
}
})
}
}
EDIT:
I tried to do it with async.each and async.parallel, but didn't succeed, can anyone show me the right way to implement it?
Removed newArray since you don't need it for anything useful, it was wasting CPU time and was a horrendous way of tracking what was done. A simple counter would have done the tricks.
Gone ES6 since it's 2016. Also added semi colon because you were using them inconstitently.
Also, doAll is not a meaningful name.
'use strict';
const async = require('async');
let array = [/*data*/];
console.log('START ' + (new Date()));
//Asynchronously iterate throught the array
async.each(array, (item, callback) => {
//item is your array[i]
async.each(item.Langs, (lang, callback) => {
//lang is your array[i].Langs[j]
let lan = convertIsoCode(item.IsoCode),
fileName = item.Name + '_' + lan,
country = item.Country;
//Apply your functions
getNews(c, lan).then((newsResults) => {
getWavFile(newsResults, lan, fileName).then((wavResults) => {
uploadToS3(country,lan,fileName).then((s3Results) => {
//Everything is OK, callback without error
callback();
}, (s3err) => {
//Raise the error
callback(s3err);
});
}, (waverr) => {
console.log('wav error: ',waverr);
//Raise the error
callback(waverr);
});
}, (newserr) => {
console.log('news error: ',newserr);
//Raise the error
callback(newserr);
});
}, (error) => {
callback(error);
});
}, (error) => {
//If a error was raised, everything pending will be aborted and the error will be displayed
if(error) {
console.log(error);
//Else, just report it did fine
} else {
console.log('OK');
}
});

Uncaught TypeError in jsPdf autotable

Am trying to print the dynamic data's into pdf file using jsPdf Auto-table . When am doing this i got some kind of error's like
The headers should be an object or array, is: function (jspdf.plugin.autotable.js:10 )
The data should be an object or array, is: function (jspdf.plugin.autotable.js:10)
TypeError: t.forEach is not a function (angular.js:12314)
Here is my code -
var getColumns = function () {
return [
{ title: "ID", dataKey: "id" },
{ title: "Name", dataKey: "first_name" },
{ title: "Email", dataKey: "email" },
{ title: "City", dataKey: "city" },
{ title: "Country", dataKey: "country" },
{ title: "Expenses", dataKey: "expenses" }
];
};
function getData(mainSteps) {
mainSteps = mainSteps || 4;
//var sentence = faker.lorem.words(12);
var data = [];
for (var j = 1; j <= rowCount; j++) {
data.push({
id: j,
first_name: this.getSteps(),
email: this.getSteps(),
country: this.getSteps(),
city: this.getSteps()(),
expenses: this.getSteps()
// text: shuffleSentence(sentence),
//text2: shuffleSentence(sentence)
});
}
return data;
}
var pdfsize = 'a4';
var doc = new jsPDF('p', 'pt', pdfsize);
doc.autoTable(getColumns, getData, {
theme: 'grid', // 'striped', 'grid' or 'plain'
headerStyles: {
fillColor: [12, 234, 227],
textColor: [12, 1, 1]
},
// margin: { top: 50, left: 20, right: 20, bottom: 0 },
styles: {
overflow: 'linebreak',
columnWidth: 88
},
beforePageContent: function (data) {
doc.text("Process Name :" + mainData.name + " || " + "Description :" + mainData.description, 40, 30);
},
//startY: doc.autoTableEndPosY() + 20,
columnStyles: {
0: { columnWidth: 200 }
}
});
//startY: doc.autoTableEndPosY() + 20
doc.save(mainData.name + ".pdf");
Note : If the error is in my code mean's i can find the solution for that, But it says error is in (jspdf.plugin.autotable.js:10 ) and (angular.js:12314) so am getting confused here. Can someone clarify me please.
As the errors explain the input data must be arrays or objects. In your case that simply means calling the functions instead of sending them to autotable. Replace this
doc.autoTable(getColumns, getData, {...});
with
doc.autoTable(getColumns(), getData(), {...});

Is it possible to populate jstree using a loop?

Hi I'd like to know if its possible to populate my jstree using a loop instead of hard-coding each node. Below is my code:
api.call("Get", {
typeName: "Device"
}, function (result) {
$('#jstree').jstree({
'plugins': ["checkbox", "sort"],
'core': {
'data':
[
{ id: result[0].id, text: result[0].name },
{ id: result[1].id, text: result[1].name }
]
}
});
});
I make an api call then populate my tree with the returned results. How can I format my JSON using a loop?
This is the main part I need to change:
[
{ id: result[0].id, text: result[0].name },
{ id: result[1].id, text: result[1].name }
]
This is what I've tried:
[
function () {
for(var i = 0; i < result.length; i++){
{ id: result[i].id, text: result[i].name }
}
}
]
Thank you.
Sure.
api.call("Get", {
typeName: "Device"
}, function (result) {
$('#jstree').jstree({
'plugins': ["checkbox", "sort"],
'core': {
'data': (function () {
var results = [];
for(var i = 0; i < result.length; i++){
results.push({ id: result[i].id, text: result[i].name });
}
return results;
})()
}
});
});

Categories