I am working on a MEAN stack app, and I'm trying to create a couple of API endpoints that the Angular client can $http.get, with simple JSON files populated with dummy data.
Here's the orders.json file I'm trying to test it with:
[
{
"order_status":"Shipped",
"order_qty":30
},
{
"order_status":"Shipped",
"order_qty":6
}
]
For example, the api route to $http.get:
apiRouter.get('/:fileName', queries.getStaticJSONFileForDevelopment);
But when I try to use express's sendFile method with a local .json file, like orders.json:
queries.js:
exports.getStaticJSONFile = function(req, res) {
var fileName = req.params.fileName;
console.log('path: ' + path.normalize(__dirname + '/' + fileName));
res.sendFile(path.normalize(__dirname + '/' + fileName), function(err) {
if (err) return res.send({ reason:error.toString() });
});
};
The console.log tells me I'm pointed at the correct path to the file, but Postman delivers this error:
TypeError: undefined is not a function
at Object.exports.getStaticJSONFile [as handle] (path/to/queries.js:260:7)
// queries.js:260:7 points to the 's' in 'sendFile' above
However, when I just send the json data by itself:
res.send([{"order_status":"Shipped","order_qty":30},{"order_status":"Shipped","order_qty":6}]);
...the endpoint renders the data as you would expect. Am I trying to get the sendFile method to do something it's not meant to do, or is there something I'm missing? Thanks very much for any advice you may have!
If You want to read json file and response with json so You can try this:
var jsonfile = require('jsonfile');
exports.getStaticJSONFile = function(req, res) {
var fileName = req.params.fileName;
var file = path.normalize(__dirname + '/' + fileName);
console.log('path: ' + file);
jsonfile.readFile(file, function(err, obj) {
if(err) {
res.json({status: 'error', reason: err.toString()});
return;
}
res.json(obj);
});
};
Related
I have an express service which has an endpoint that consumes a POST call with form-data in XML.
Postman Call
I'm using multer and express-xml-bodyparser and my index.js looks like:
'use strict';
const express = require('express');
const app = express();
const xmlparser = require('express-xml-bodyparser');
const multer = require('multer')
const upload = multer()
const redact = { redact: ['body.*', 'value.body'] };
const modsRoute = require('./routes/mods');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(xmlparser());
app.use(upload.none());
app.post('/request', modsRoute.postMethod)
module.exports = app;
The problem is that when I try to print the content of the request body in my router method:
const postMethod = async (req, res, next) => {
try {
console.log('body: ', req.body);
res.status(200).send();
} catch (err) {
next(err);
}
};
I get a weird object:
body: [Object: null prototype] {
'api-key': '1a393779-c191-11e3-ae50-80c16e6a4098',
data: '<subscriber>\n' +
'\t<action>add</action>\n' +
'\t<customer_id>529</customer_id>\n' +
'\t<subscriber_details>\n' +
' <unique_id>123UniqueID</unique_id>\n' +
'\t\t<firstname>First</firstname>\n' +
'\t\t<lastname>Test</lastname>\n' +
'\t\t<address1>999 Street</address1>\n' +
'\t\t<address2></address2>\n' +
'\t\t<city>Scottsdale</city>\n' +
'\t\t<state>AZ</state>\n' +
'\t\t<zip>85253</zip>\n' +
' <email>email#infoarmor.com</email>\n' +
' <dob_month>00</dob_month>\n' +
'\t\t<dob_day>00</dob_day>\n' +
'\t\t<dob_year>0000</dob_year>\n' +
'\t\t<phone>9999999999</phone>\n' +
'\t\t<options>\n' +
'\t\t\t<plan_type>1</plan_type>\n' +
' <ew_status>0</ew_status>\n' +
'\t\t</options>\n' +
'\t\t<billing_information>\n' +
'\t\t\t<bill_type>prd</bill_type>\n' +
'\t\t</billing_information>\n' +
'\t</subscriber_details>\n' +
'</subscriber>'
}
As it can be seen, the object contains all the newline and whitespace characters and it hasn't really converted it into JSON.
I also tried to convert the whole body into JSON with JSON.parse() but I got an exception thrown. I also tried to first stringify() the body and then parse it.
In that case, I could only get the data field but I was again an expection when trying to get the api-key field.
Do I need to add any other middleware in order to get at least a correct JSON object of req.body even though the field data is still in XML and not JSON?
You can send json data to user using like this
const postMethod = async (req, res, next) => {
try {
res.json({"Hello":"World"});
// you can send anything json back including req.body like
// this res.json(req.body);
} catch (err) {
next(err);
}
};
I am currently facing a similar problem to this post. I managed to resolve my initial issue after referencing solutions posted there. However, when i tried to post a image that is less than 1MB and is a jpg formatted image( which i managed to do before the editing), it now fails and state that TypeError: Cannot read property 'filename' of undefined.
My app.js code:
const upload = multer({
dest: storage,
storage: storage,
limits: {
fileSize: 1024 * 1024
},
fileFilter: function(req, file, callback,error) {
var ext = path.extname(file.originalname);
var error_msg = error instanceof multer.MulterError;
if(ext !== '.jpg') {
req.fileValidationError = "Not a jpg file!";
return callback(null, false, req.fileValidationError);
}
if(error_msg) {
req.fileSizeError = "Image more than"
return callback(null, false, req.fileSizeError)
}
callback(null,true)
}
});
app.post("/upload", function (req, res, next) {
upload.single('name')(req, res, function (error) {
if(req.fileValidationError) {
res.status(500).send({message:req.fileValidationError});
}
else {
if(error.code === 'LIMIT_FILE_SIZE') {
req.fileSizeError = "Image more than 1MB!";
res.status(500).send({message:req.fileSizeError});
}
else {
console.log('File Received!');
console.log(req.file);
var sql = "INSERT INTO `file`(name,description,type,size) VALUES('" + req.file.filename + "', '" + (req.file.encoding + "_" + req.file.destination + "_" + req.file.path)+ "', '" + req.file.mimetype + "', '" + req.file.size + "')";
db.query(sql, (error, results) => {
console.log('Inserted Data!');
});
const message = "Successfully Uploaded!"
res.status(200).send({message:message, file_details:req.file})
}
}
})
})
The array does only contain objects, not the filename property. The first object in the array does have the filename property. Select the first and only item in it using req.files['image'][0].filename or req.files[0].filename and it should work.
It looks like the error handling isn't right, during file saving in particular; in which the resulting errors are not being handled. For example, try deleting the destination directory "uploads" and then upload a file, TypeError: Cannot read property 'filename' of undefined will be thrown again!
To resolve this and to determine what exactly is the error, you should handle the upload.single() error callback.
app.post("/upload", function (req, res, next) {
upload.single('name')(req, res, function (error) {
if (error) {
console.log(`upload.single error: ${error}`);
return res.sendStatus(500);
}
// code
})
});
Make sure your sending in your request header "Content-Type": "multipart/form-data"
Bingo!! resolved this
For me I was just sending the image name and not the object (const file = event.target.files[0]; file in this case).
Hope this help you:)
Add this enctype="multipart/form-data" in your form tag its like:
<form action="/admin/banner/update?id={{bannerEdit._id}}" enctype="multipart/form-data" method="post">
This is what my code looks like:
'use strict';
process.env.AWS_PROFILE
// Load the AWS SDK for Node.js
const AWS = require('aws-sdk');
// Create EC2 service object
var ec2 = new AWS.EC2({apiVersion: '2016-11-15'});
// Load credentials and set region from JSON file
AWS.config.loadFromPath('/Users/testuser/.aws/credentials');
// Load in security group parameters
const securityParams = require('./securityParams.json');
module.exports = {
//Exports creation of Security Groups
CreateSecurityGroup: (req, res) => {
ec2.createSecurityGroup(securityParams, function(err, data) {
if (err) {
return (console.log("Error", err));
}
// Pass the Json as a parameter in this function
ec2.authorizeSecurityGroupIngress(securityParams, function(err, data) {
if (err) {
res.serverError(err, err.stack);
} else {
res.ok(data);
console.log('Ingress Security Rules Created');
}
})
// Pass the Json as a parameter in this function
ec2.authorizeSecurityGroupEgress(securityParams, function(err, data) {
if (err) {
res.serverError(err, err.stack);
} else {
res.ok(data);
console.log('Egress Security Rules Created');
}
})
})
}
}
I'm trying to have the script load configurations from two files; one aws credentials file, and one json. However its throwing errors on the credentials file which looks like this:
[default]
aws_access_key_id=**************
aws_secret_access_key**************
I'm not sure what I'm missing to get it to read the properties in correctly.
Here is the error I'm seeing:
undefined:1
[default]
^
SyntaxError: Unexpected token d in JSON at position 1
at JSON.parse (<anonymous>)
credentials is a plain Ascii file, it's not json file
// Load credentials and set region from JSON file
AWS.config.loadFromPath('/Users/testuser/.aws/credentials');
You can check file type with command file /Users/testuser/.aws/credentials
sample snippet to read props file and set AWS config
var PropertiesReader = require('properties-reader');
var AWS = require('aws-sdk')
var properties = PropertiesReader('/Users/username/.aws/credentials');
AWS.config.update({
accessKeyId : properties.get('aws_access_key_id'),
secretAccessKey : properties.get('aws_secret_access_key'),
region : 'us-west-2'
})
console.log(AWS.config)
Ref:https://www.npmjs.com/package/properties-reader
I use express router to catch a ajax post data, which is a stringified JSON obj:
router.all('/ajax/setup/save/asset', function (req, res) {
console.log('POST: /ajax/setup/save/asset');
var fileName = path.join(jsonFileNamePrefix, jsonFileName_asset);
req.on('data', function(chunk) {
console.log('POST: DATA: ' + chunk);
fd = fs.openSync(fileName, 'w');
console.log('Opened file: ' + fileName);
fs.writeSync(fd, chunk);
console.log('Wrote ' + chunk + ' into file ' + fileName);
fs.closeSync(fd);
console.log('Closed file: ' + fileName);
res.end();
console.log('res.end()');
});
});
Then the console logs:
POST: /ajax/setup/save/asset
POST: DATA: {"asset":"test"}
Opened file: /srv/data/asset.json
Wrote {"asset":"test"} into file /srv/data/asset.json
Closed file: /srv/data/asset.json
res.end()
However, the file is actually written as:
[123,34,97,115,115,101,116,34,58,34,116,101,115,116,34,125]
Tried telling fs.writeSync to use 'utf8', 'hex' encoding, still got same result.
Also tried JSON.parse and then JSON.stringify the incoming data chunk, didn't help either..
The req object in your code is actually an instance of the http.IncomingMessage stream.
When it provides information via the data event, this information is provided as a buffer.
Additionally, not all the data for the request is guaranteed to be available in the first call to the handler.
There are several ways to capture this data into a useable string. You could create a new string and simply concat the chunks together
router.all('/ajax/setup/save/asset', function (req, res) {
var buf = ''
req.on('data', function(chunk){
buf += chunk.toString();
});
req.on('end', function(){
console.log(buf);
});
});
Whenever i am giving a single data element in my json file my code works fine,but as soon as i give an array of elements it starts showing undefined on the client side.
This is my server side code.
var app = require('express')()
, server = require('http').createServer(app)
, io = require('socket.io').listen(server);
var fs= require('fs');
server.listen(3000);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/cli_index.html');
});
io.sockets.on('connection', function (socket) {
var file = __dirname + '/data.json';
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.log('Error: ' + err);
return;
}
data = JSON.parse(data);
// You can save those values somewhere or just log them to the console
console.log(data);
socket.emit('news', { hello: data});
});
});
This is my client side code.
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
JSON.stringify(data);
for(var i=0;i<2;i++){
document.write(data[i].hello.name);
}
});
</script>
This is my external json file.
[{"name":"hey"},{"name":"Gouraw"}]
In this server side code:
socket.emit('news', { hello: data});
...you're sending the array as the hello property of an object, but this client-side code:
document.write(data[i].hello.name);
...is expecting the top-level to be an array, with individual hello properties for each entry. Change that to:
document.write(data.hello[i].name);
...so you're indexing into the array.
It would probably be best, as well, to limit your loop using the array's length rather than a hardcoded value:
for(var i=0;i<data.hello.length;i++){