How to get parameters of `req` in express node server - javascript

I have two paramaters in my UI. One is a file and another is dataObject. In the utils, I have written code as :
importPlan: function (formData, planDTO) {
return axios.post(`${importPlanAPIPath}`, planDTO, formData);
}
In the router, I am sending this as :
router.post('/plans/importPlan/', planController.importPlan);
and in the controller, I have written the request as :
async importPlan(req, res, cb) {
let plan,
planDTO = req.body;
const formData = new FormData(),
file = req.files.file;
formData.append('file', file.data);
console.log('planDTO => ', planDTO);
console.log(file.data, file.name);
try {
plan = await req.clients.planClient.importPlan(formData, planDTO);
} catch (err) {
return cb(err);
}
res.json(plan);
}
In the req.body, I am getting the planDTO but I am not getting any req.files in the req. Also I am using bodyparser to parse the request. I am also using busboybodyparser for multipart/form-data.
Can Somebody please tell what I am doing wrong?
Thanks in advance.

yourparam is parameter name
router.post('/plans/importPlan/:yourparam', planController.importPlan);
async importPlan(req, res, cb) {
var yourparam= req.params.yourparam;
..........
res.json(plan);
}
use this module for file upload https://www.npmjs.com/package/multer

Related

How to send data from NodeJS server side to the JS client side, only when data is ready?

On my website, when the user clicks on a button, some user's data will be stored in a database and after that I want the server to send notification data to the Javascript frontend file to change the UI.
Right now, the Js file (index.js) receives data right after the website loads (always false). I want it to be received only when the data is ready on the server.
I searched a lot but couldn't find an answer to my problem?
I appreciate any help :)
server.js
var requestValidation = false;
app.post("/", function(req, res){
var name = req.body.personName;
var email = req.body.personEmail;
var collabTopic = req.body.collabTopic;
const newUser = new User({ //mongoDB schema
name: name,
email: email,
collabTopic: collabTopic
});
newUser.save(function(err){ //adding data to mongoDB
if(!err){
requestValidation = true;
}
});
});
app.get("/succ", function(req, res){
res.json(requestValidation);
});
index.js
const url = "http://localhost:3000/succ";
const getData = async (url) => {
try {
const response = await fetch(url);
const json = await response.json();
console.log(json);
} catch (error) {
console.log(error);
}
};
getData(url);
I'm not sure this is completely the answer you're looking for, but it's definitely a tool/feature to consider as you rework your approach.
app.post("/", async (req, res) => {
let result = await INSERT MONGODB UPDATE OR INSERT FUNCTION;
res.render("YOUR TEMPLATE", result);
});
You probably can't plug and play this, but when you finish a MongoDB operation, it returns a json object with some details on whether or not there was success. For example, a MongoDB insert operation returns something like this (stored in the variable result that I created)
{ "acknowledged" : true, "insertedId" : ObjectId("5fd989674e6b9ceb8665c57d") }
and then you can pass this value on as you wish.
Edit: This is what tkausl referred to in a comment.
Here is an example if you want to pass the content of a txt file to the client with express and jquery:
in express:
app.get('/get', (req, res) => {
fs.readFile('test.txt', (err, data) => {
if (err) throw err;
return res.json(JSON.parse(data));
})
})
jquery in client side:
$.getJSON( "http://localhost:3000/get", function( data ) {
geojsondata1 = JSON.stringify(data)
}
now you can do anything you want with the variable data

How to return an error back to ExpressJS from middleware?

I am using [Multer][1] as middleware to process multipart form data. Multer offers some configuration options for setting destination of file uploads and names called diskStorage. It is within this area that one can do some error checking and control whether Multer authorises a file upload or not.
My Express route is basically this:
expressRouter.post(['/create'],
MulterUpload.single("FileToUpload"), // if this throws an error then have Express return that error to the user
async function(req, res) {
// handle the form text fields in req.body here
});
MulterUpload.single() takes the file input field named "FileToUpload" and sends it off to do this:
const MulterUpload = multer({
storage: MulterStorage
)}
const MulterStorage = multer.diskStorage({
destination: async function (req, file, cb) {
try {
if ("postID" in req.body && req.body.postID != null && req.body.postID.toString().length) {
const Result = await api.verifyPost(req.body.postID)
if (Result[0].postverified == false) {
const Err = new Error("That is not your post!");
Err.code = "ILLEGAL_OPERATION";
Err.status = 403;
throw(Err); // not authorised to upload
} else {
cb(null, '/tmp/my-uploads') // authorised to upload
}
}
} catch (err) {
// How do I return the err back to Express so it can send it to the user? The err is an unresolved Promise as I am using async/await
}
}
,
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
I just can't seem to work out how to get the error from MulterStorage back to Express so that it is sent back the browser/user as an error.
[1]: https://www.npmjs.com/package/multer
You can call the completion callback with an Error object as the first argument. So, instead of
cb(null, someResult)
you call the callback with an error object
cb(new Error("I got a disk error"));
Then, if you have multer set up as plain middleware, this will result in next(err) being called and in Express, your generic error handler will receive the error.
Here are a couple examples:
https://www.npmjs.com/package/multer#error-handling
https://github.com/expressjs/multer/issues/336#issuecomment-242906859

How to parse an object sent from react frontend in express.js?

So in my react front-end, I am using the 'react-drop-to-upload' module to allow the user to drag a file and upload. I followed the example on the npm module page and created a handler called handleDrop. The code looks like:
handleDrop(files) {
var data = new FormData();
alert((files[0]) instanceof File);
files.forEach((file, index) => {
data.append('file' + index, file);
});
fetch('/file_upload', {
method: 'POST',
body: data
});
}
At my express backend, I have the following code:
app.post('/file_upload', function(req , res){
var body = '';
req.on('data', function (data) {
body += data;
});
var post = "";
req.on('end', function () {
//post = qs.parse(body);
console.log(body);
// this won't create a buffer for me
//var fileBuffer = new Buffer(body);
//console.log(fileBuffer.toString('ascii'));
//pdfText(body, function(err, chunks) {
//console.log(chunks);
//});
});
//console.log(typeof post);
});
If I drop a txt file and do a console log on the body, it would give me:
------WebKitFormBoundaryqlp9eomS0BxhFJkQ
Content-Disposition: form-data; name="file0"; filename="lec16.txt"
Content-Type: text/plain
The content of my data!
------WebKitFormBoundaryqlp9eomS0BxhFJkQ--
I am trying to use the pdfText module which takes in a buffer or a pathname to the pdf file, extract text from it into an array of text 'chunks' . I want to convert the body object into a buffer using var fileBuffer = new Buffer(body); but that won't work. Can someone help me with this? Thanks!
You need a parser for multi-part data. You can look into multer regarding that.
Example code for you,
app.post('/file_upload', function(req , res){
var storage = multer.diskStorage({
destination: tmpUploadsPath
});
var upload = multer({
storage: storage
}).any();
upload(req, res, function(err) {
if (err) {
console.log(err);
return res.end('Error');
} else {
console.log(req.body);
req.files.forEach(function(item) {
// console.log(item);
// do something with the item,
const data = fs.readFileSync(item.path);
console.log(data);
});
res.end('File uploaded');
}
});
});
To understand the example code in depth, head here. Remember, you will get the file data as a buffer and not as actual data.

How to configure API endpoint to receive file from ember-uploader component

I'm trying to figure out how to use ember-uploader, I have the following component (like the one in the README)
export default EmberUploader.FileField.extend({
filesDidChange: function(files) {
const uploader = EmberUploader.Uploader.create({
url: (ENV.APP.API_HOST || '') + '/api/v1/images/',
});
console.log(uploader);
if (!Ember.isEmpty(files)) {
var photo = files[0];
console.log(photo);
uploader.upload(photo)
.then(data => {
// Handle success
console.log("Success uploading file");
console.log(data);
}, error => {
// Handle failure
console.log("ERROR uploading file");
console.log(error);
});
}
}
});
The express API endpoint is listening for a POST request.
var saveImage = (req, res, next) => {
let body = req.body;
res.json({
data: body
});
};
But the body is empty after the request is done. I really don't know how to implement the API endpoint in order to get the file, I tried to see the req object and it doesn't contains the file.
Debugging it, After select a file using the component I get the following info in the console.
Seems that the API endpoint works because I get the following output:
POST /api/v1/images/ 200 27.284 ms - 11
But I can't get the file.
SOLUTION
In Express 4, req.files is no longer available on the req object by
default. To access uploaded files on the req.files object, use a
multipart-handling middleware like busboy, multer, formidable,
multiparty, connect-multiparty, or pez.
Following this blog, the code below was added to the API and the ember-uploader code posted in the question worked as expected.
import formidable from 'formidable';
var saveImage = (req, res, next) => {
var form = new formidable.IncomingForm();
form.parse(req);
form.on('fileBegin', function (name, file){
file.path = __dirname + '/tmp/' + file.name;
});
form.on('file', function (name, file){
res.json({
data: file.name
});
});
};

Node JS file transfer via Request Module

I am creating a node server to which files can be uploaded an then sent to a storage server which is also using node.
To do this i am using this method described on the Form-Data module page:
var formData = {
my_field: 'my_value',
my_file: fs.createReadStream(__dirname + '/unicycle.jpg'),
};
request.post({url:'http://service.com/upload', formData: formData}, function(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
My Problem is that when i try to write the file on the storage server it creates a text file with the content [object Object].
Here is my code:
main.js
var form = new formData();
form = {
'oldFileName': oldName,
'newFileName': newName,
'file': fs.createReadStream(FILEPATH),
};
request.post({url:'http://127.0.0.1:9001/upload', form: form}, function(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
});
storage.js
app.post('/upload', function(req,res){
//Filenames are displayed without problem
console.log(req.body.newFileName);
console.log(req.body.oldFileName);
fs.writeFile('./testing/' + req.body.newFileName, req.body.file, function(err) {
if(err) {
return console.log(err);
}
})
I'm sure I'm missing something really obvious, but I cant seem to get it to work.
You are passing formData in form option of request that changes the content to application/x-www-form-urlencodedinstead of multipart/form-data.
app.js
var form = {
'oldFileName': oldName,
'newFileName': newName,
'file': fs.createReadStream(FILEPATH),
};
request.post({url:'http://127.0.0.1:9001/upload', formData: form}, function(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
});
Also, to parse multipart/form-data, you have to use multer or similar library, body-parser doesn't work in that case. Please find following working storage.js code for saving file.
storage.js
var multer = require('multer')
var upload = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './testing/');
},
filename: function (req, file, cb) {
cb(null, req.body.newFileName);
}
})
}).single('file');
app.post('/upload', function(req, res, next){
upload(req, res, function (err) {
if(err){
return res.send(err);
} else{
return res.send("Upload successfully");
}
});
});
Hope it helps you.
Alternatively, wrapping the [object Object] within a JSON.stringify() method should reveal the literal string content of the objects.
In my situation I was using the NodeJS Library for YouTube video uploads, following OAuth2.0 protocol.
Within this standard, you post your Client ID and Client Secret to authenticate your usage of the YouTube Data API.
In return, the server returns tokens, in the form of an Access Token and Refresh Token. These tokens are need to refresh the ability to use the API without expiry.
However, I was receiving (Object, object) in the terminal when requesting the 'tokens'....
Logger.log(Got the tokens:(token));
To rectify the problem and reveal the tokens in the terminal in a readable string format, I done the following...
Logger.log(Got the tokens: ${JSON.stringify(token)});
Now I can use the tokens accordingly.
//Note - ES6 backticks are used as string literals, but the backticks don't seem to be displaying in the parameters.

Categories