I'm working on an app that takes a list of latitudes and longitudes from a mongodb database and puts them onto a google map as points, but I'm having an issue parsing the JSON that is outputted by mongoose from node.js, here's the code I'm using to parse the JSON. The error that the browser is giving me is:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
var jsonData = JSON.parse('http://hanky-ranky.azurewebsites.net/listbathroom');
for (var i = 0; i < jsonData.length; i++) {
var bathroom = jsonData[i];
console.log(bathroom.lat);
}
Here's the code I used to generate the JSON inside of node.js using mongoose
var express = require('express');
var router = express.Router();
var mongoose= require("mongoose");
//Connect to mongo DB
mongoose.connect('mongodb://test:test#ds040898.mongolab.com:40898/MongoLab-0');
var myDB = mongoose.connection;
//Error handling if conncetion fails
myDB.on('error', console.error.bind(console, 'connection error:'));
//Check if successful connection is made
myDB.once('open', function callback () {
//console.log("MY DB Connected with Mongoose");
});
//create an employee schema for operation with mongo
var bathroomSchema = mongoose.Schema(
{
'name': String,
'address' : String,
'lat': String,
'lng': String,
'type': String,
},
{
collection:'bathrooms'
}
);
// model reference
var bathrooms = mongoose.model('bathrooms', bathroomSchema);
function readBathrooms(callback)
{
bathrooms.find({},function (error, result) {
callback(error, result);
});
}
router.get('/', function(req, res, next) {
readBathrooms(function(error,result){
if (error) {
res.send({'result':'error'});
console.log("Error!");
}else {
//console.log(result);
res.render('listbathroom', {"result": result });
}
});
});
module.exports = router;
And here's the jade file that is called for displaying the JSON
!{result}
As Kevin B pointed out to me, I wasn't actually parsing JSON, but instead was attempting to parse a URL as JSON. I solved my problem with the following code
var xmlhttp = new XMLHttpRequest();
var url = "http://hanky-ranky.azurewebsites.net/listbathroom";
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var thejson = JSON.parse(xmlhttp.responseText);
logjson(thejson);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
function logjson(arr) {
var i;
for(i = 0; i < arr.length; i++) {
console.log(arr[i].lat);
}
}
Related
Key-value pairs like name are appended to form-data in a client-side XMLHttpRequest and sent with file to be uploaded.
How can I extract those values on the server side, which is using Node.js.
Browser:
formdata = new FormData();
for( var x = 0;x < files.length;x = x+1){
formdata.append('file',files[x]);
}
formdata.append('name',name); //name appended here to form-data
formdata.append('email',email);
formdata.append('reason',reason);
formdata.append('location',location);
var xhr = new XMLHttpRequest();
var url = "/sign_8081";
xhr.open("POST" ,url);
xhr.withCredentials = true;
Node.js Server:
router.post('/sign_8081', (req, res) => {
console.log("sign 8081called"+JSON.stringify(req.body))
console.log(req.query.name);
console.log(req.body.name); //want name key value in Node.js code
let body = '';
var rb;
req.on('data', chunk => {
body += chunk.toString(); // convert Buffer to string
});
req.on('end', () => {
rb = parse(body)
console.log(rb.name);
});
console.log(req.file.filename)
res.send(req.file.filename)
});
If you are using expressjs, use body-parsing middlewares such as express.json() or express.urlencoded(), then your can access form input req.body.
var app = express()
app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true })) // for parsing application/x- www-form-urlencoded
router.post('/sign_8081', (req, res) => {
console.log("sign 8081called"+JSON.stringify(req.body))
console.log(req.query.name);// do not use this
console.log(req.body); // object of inputs
let body = '';
var rb;
req.on('data', chunk => {
body += chunk.toString(); // convert Buffer to string
});
req.on('end', () => {
rb = parse(body)
console.log(rb.name);
});
console.log(req.file.filename)
res.send(req.file.filename)
});
For more on expressjs request object expressjs docs
so I'm trying to create an application for the Google Assistant and the data for my application is stored in an online XML, however, I am not sure how I am supposed to extract the specific data that I require from the XML.
I have tried to fix this by indexing the results of the XML parser however I receive either undefined errors or cannot read property errors.
var eyes = require('eyes');
var https = require('https');
var fs = require('fs');
var xml2js = require('xml2js');
var parser = new xml2js.Parser({ attrkey: "ball"});
parser.on('error', function(err) { console.log('Parser error', err); });
var data = '';
https.get('https://www.national-lottery.co.uk/results/euromillions/draw-history-full/xml', function(res) {
if (res.statusCode >= 200 && res.statusCode < 400) {
res.on('data', function(data_) { data += data_.toString(); });
res.on('end', function() {
console.log('data', data);
parser.parseString(data, function(err, result) {
toUse = result['draw-results']['game']['balls']['ball'][1];
console.log(toUse);
console.log('FINISHED', err, result);
});
});
}
});
I expect to receive an output of the first ball number called, however, I cannot get the data out other than printing the entire XML.
I get the output 4 for the path result['draw-results'].game[0].balls[0].ball[0]['_'].
I am newbie in Nodejs world. I am trying to insert data in MongoDB using Mongoose. The idea is
- I will have a server running on node
- any incoming POST data will be saved in Mongo.
The problem when the below code is run no data gets saved in MongoDB and also no error is shown. Am i missing something here. Any help will be really appreciated.
I have the below code that writes data in mongoDB for an incoming http request.
var http = require('http') // http module
, fs = require('fs') // file system module
, qs = require('querystring') // querystring parser
, mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/app_data_db");
var db = mongoose.connection;
var appDataSchema = new mongoose.Schema({
record_id: Number,
app_version: Number,
imei: String,
created_time: Date,
device_uid: String,
model: String
});
var appDataModel = mongoose.model("app_data_collection",appDataSchema);
var PORT=8080;
http.createServer(function(req,res){
if(req.method == "POST") {
var POST = {};
//parse query string
req.on('data', function(data) {
data = data.toString();
data = data.split('&');
for (var i = 0; i < data.length; i++) {
var _data = data[i].split("=");
POST[_data[0]] = _data[1];
}
db.once('open', function (callback) {
appDataModel.create({
record_id: POST["id"],
app_version: POST["app_version"],
imei: POST["imei"],
created_time: new Date((parseInt(POST["created_time"]) + 19800) *1000), // to set correct time zone IST
device_uid: POST["device_uid"],
model: POST["model"]
});
});
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('saved to DB:'+POST["id"]+'\n');
console.log('saved to DB:'+POST["id"]+'\n');
});
mongoose.disconnect();
}
}).listen(PORT);
To test this I am manually firing this curl call:
curl -X POST --data "id=58648148&app_version=4.8&imei=355886053224492&created_time=1417372202&device_uid=e385c8a5a4c01304&model=GT-I9082" http://localhost:8080
There are couple problems with your code:
1) you call mongoose.disconnect outside of the callback, which means that it's called before the callback is executed
2) you're creating the model inside the callback, but sending the response outside of it, so the response is sent before the model is created
3) and finally create method provides a callback when the entity is saved to the db, which you don't use it all
Here's the modified code:
mongoose.connect("mongodb://localhost/app_data_db");
db.on('open', function() {
http.createServer(function(req, res) {
if(req.method == "POST") {
var POST = {};
//parse query string
req.on('data', function(data) {
data = data.toString();
data = data.split('&');
for (var i = 0; i < data.length; i++) {
var _data = data[i].split("=");
POST[_data[0]] = _data[1];
}
appDataModel.create({
record_id: POST["id"],
app_version: POST["app_version"],
imei: POST["imei"],
created_time: new Date((parseInt(POST["created_time"]) + 19800) *1000), // to set correct time zone IST
device_uid: POST["device_uid"],
model: POST["model"]
},
function(err){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('saved to DB:'+POST["id"]+'\n');
console.log('saved to DB:'+POST["id"]+'\n');
mongoose.disconnect();
});
});
}
}).listen(PORT);
});
I think I got this working. I have moved the mongoose connection inside. Rest all is same. Since I wanted to post the code hence answering instead of commenting. This may help others. Here is the complete code
var http = require('http') // http module
, fs = require('fs') // file system module
, qs = require('querystring') // querystring parser
, mongoose = require('mongoose');
var appDataSchema = new mongoose.Schema({
record_id: Number,
app_version: Number,
imei: String,
created_time: Date,
device_uid: String,
model: String
});
var appDataModel = mongoose.model("app_data_collection", appDataSchema);
var PORT = 8080;
http.createServer(function(req, res) {
if (req.method == "POST") {
var POST = {};
//parse query string
req.on('data', function(data) {
data = data.toString();
data = data.split('&');
for (var i = 0; i < data.length; i++) {
var _data = data[i].split("=");
POST[_data[0]] = _data[1];
}
mongoose.connect("mongodb://localhost/app_data_db");
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
appDataModel.create({
record_id: POST["id"],
app_version: POST["app_version"],
imei: POST["imei"],
created_time: new Date((parseInt(POST["created_time"]) + 19800) * 1000), // to set correct time zone IST
device_uid: POST["device_uid"],
model: POST["model"]
}, function(err) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('saved to DB:' + POST["id"] + '\n');
console.log('saved to DB:' + POST["id"] + '\n');
mongoose.disconnect();
});
});
});
}
}).listen(PORT);
I'm experiencing an issue where a POST request I make fails with error code 500 and nothing is printed in my server side error log. It's almost as if the cloud method doesn't exist for it.
What is strange though, is that the same POST request performs fine with smaller files. It starts to fail when the file gets to around 1.4 MB. I've tried changing the limit parameter of express.bodyParser like so "app.use(express.bodyParser( { limit: 10000000 } ));", however this makes no difference.
Here's some code:
function uploadFile(pageState)
{
var reader = new FileReader();
reader.onload = function()
{
var data = reader.result;
var byteArrayObj = new Uint8Array(data);
var byteArray = new Array(byteArrayObj.length);
for(i=0; i<byteArray.length; i++) {
byteArray[i] = byteArrayObj[i];
}
var json = { data: byteArray };
var jsonString = JSON.stringify(json);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "/assetUploader/"+pageState.assetIdentifier+"/"+pageState.fileName+"/"+pageState.isAssetBundle+"/"+pageState.uploadToProduction, true);
xmlhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.onload = function(evt) {
...
};
xmlhttp.send(jsonString);
};
reader.readAsArrayBuffer( pageState.fileRef );
}
On the cloud side:
app.post('/assetUploader/:fileIdentifier/:fileName/:isAssetBundle/:useProd', function(req, res)
{
console.log("assetUpload Post");
var fileId = req.params.fileIdentifier;
var fileName = req.params.fileName;
var assetBundle = req.params.isAssetBundle == "true";
var bytes = req.body.data;
var useProd = req.params.useProd == "true";
createParseFile(fileName, bytes, useProd).then( function(response) {
return currentVersionForAsset(fileId, useProd).then(function(versionNumber) {
return {
"fileIdentifier": fileId,
"file": {
"name": response.data.name,
"__type": "File"
},
"isAssetBundle": assetBundle,
"fileVersion": versionNumber+1
};
});
}).then(function(json) {
return createParseObject("DownloadableAsset", json, useProd);
}).then( function() {
res.send(200);
}, function(error) {
res.send(400, error.message);
});
});
Any help or suggestions would be much appreciated. Thanks for your time!
i suggest using res.setTimeout with a very large number of milisecs. perhaps your response simply times out, and from my experience node doesn't throw an error when it happens.
Okay here is the general goal of this code. I am using TinyPNG's API to condense a folder of png files. I have an input folder with a number of files named filename.png. This code reads the directory of file names into an array files, then creates read and write streams for those files to be sent to the API, processed, and then returned so it can be written to a file in the output folder. I know the code works for one file, but any more than that throws an exception of write after end because the pipe is automatically closed after the first one. I have tried setting up the input and output as arrays and that just throws another exception.
Any hints on how to set up multiple read and write streams would be awesome and very useful to everyone :).
Current code:
var fs = require('fs');
var inputFolder = "input/";
var outputFolder = "output/";
var https = require("https");
var key = "GETYOUROWNFREEONEFROMTINYPNG.ORG";
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var options = require("url").parse("https://api.tinypng.com/shrink");
options.auth = "api:" + key;
options.method = "POST";
console.log("Reading files...");
fs.readdir("./input", function (err, files) {
if (err) throw err;
console.log(files.length + " files read...");
var input;
var output;
var request;
for(var i = 0; i < files.length; i++)
{
input = fs.createReadStream(inputFolder + files[i]);
output = fs.createWriteStream(outputFolder + files[i]);
request = new https.request(options, function(response) {
if (response.statusCode === 201) {
/* Compression was successful, retrieve output from Location header. */
https.get(response.headers.location, function(response) {
response.pipe(output);
});
} else {
/* Something went wrong! You can parse the JSON body for details. */
console.log("Compression failed");
}
});
input.pipe(request);
}
});
Here is the fixed file for others to use thanks to the answer provided by #Wyatt:
var fs = require('fs');
var inputFolder = "input/";
var outputFolder = "output/";
var https = require("https");
var key = "WotZ46HnxPl_HwpT3uZjtY_0f8fMEiSR";
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var options = require("url").parse("https://api.tinypng.com/shrink");
options.auth = "api:" + key;
options.method = "POST";
console.log("Reading files...");
fs.readdir("./input", function (err, files) {
if (err) throw err;
console.log(files.length + " files read...");
var input, request;
for(var i = 0; i < files.length; i++){
input = fs.createReadStream(inputFolder + files[i]);
request = closureRequest(fs.createWriteStream(outputFolder + files[i]));
input.pipe(request);
}
});
function closureRequest(output){
return new https.request(options, function(response) {
if (response.statusCode === 201) {
/* Compression was successful, retrieve output from Location header. */
https.get(response.headers.location, function(response) {
response.pipe(output);
});
} else {
/* Something went wrong! You can parse the JSON body for details. */
console.log("Compression failed");
}
});
}
You are repeatedly reassigning the output variable in your loop, while the request callback is trying to refer to it. You can capture each value in a closure to get around this.
...
function closureRequest(output){
return new https.request(options, function(response) {
if (response.statusCode === 201) {
/* Compression was successful, retrieve output from Location header. */
https.get(response.headers.location, function(response) {
response.pipe(output);
});
} else {
/* Something went wrong! You can parse the JSON body for details. */
console.log("Compression failed");
}
});
}
var input
, request
;
for(var i = 0; i < files.length; i++){
input = fs.createReadStream(inputFolder + files[i]);
request = closureRequest(fs.createWriteStream(outputFolder + files[i]));
input.pipe(request);
}