Upload client file to website through node - node.js

I'm trying to achieved the following:
Client has to fill a form and submit it to the node server
If client has a business card, snap a picture and it updates the form.
I have the API to translate image to json.
But I struggle to upload that image through node.
I created an html form with an input=file.
When input is changed, Ajax is called to upload that image.
On node, the request is received and basically transferred to that other website (camcard).
Json response should be sent back to client.
I just can't achieve that..
Any idea?
Here is some code. I do a post in 2 ways (regular and Ajax)
Html client:
<form method='POST' id="formCard"
enctype='multipart/form-data'>
<input type=file class="btn btn-outline-primary" name=upfile
size=20 id="cardSelector" onChange="changeFile()">
</form>
<form method='POST' action='/postCardPic'>
Please specify a JPG file<br>
<input type=file name=upfile size=20><br><br>
<input type=submit value='Upload'>
</form>
<script>
function changeFile() {
var formData = new FormData();
formData.append( 'file', $( '#cardSelector' )[0].files[0] );
$.ajax({
data: formData,
enctype: 'multipart/form-data',
processData: false,
contentType: false,
type: "POST",
url: "/postCardPic",
success: function (response) { // on success..
console.log(response); // update the DIV
},
complete: function (data) {
hideLoader();
}
});
}
</script>
On the server side:
App.use(bodyParser.urlencoded({
extended: false,
limit: '50mb',
parameterLimit:'50000'
}));
app.use(bodyParser.json({
extended: false,
limit: '50mb',
parameterLimit:'50000'
}));
app.post('/postCardPic', function(req, response) {
var urlCamCard='http://whatever.com'
// var form = new Form();
// form.parse(req, function(err, fields, files) {
// res.writeHead(200, {'content-type': 'text/plain'});
// res.write('received upload:\n\n');
// res.end(util.inspect({fields: fields, files: files}));
// });
// form.on('file', function(name,file) {
// //stream it to localhost:4000 with same name
// fs.createReadStream(file.path).pipe(request.post(urlCamCard))
// });
request.post({
url:urlCamCard, form:req.body}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
response.end();
});
Log in both cases is the same:
Upload successful! Server responded with: ErrorCode: -1 ErrorMsg: Image data size not supported

I found the solution.
Here's is the code on the server side:
App.post("/postCardPic", function(req, res) {
try {
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {});
form.on("file", function(name, file) {
var formData = {
file: {
value: fs.createReadStream(file.path),
options: {
filename: file.originalFilename
}
}
};
request.post(
{
url: theurl,
formData: formData
},
function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error("upload failed:", err);
}
res.end(body);
}
);
});
} catch (err) {
console, log(err);
res.end();
}

Related

Why is req.file undefined in my route.post?

I am trying to send a photo from react to node server.
But i have some problems : req.file is undefined and I don't understand why
This is my react code
const formData: any = new FormData();
formData.append("file", {
uri: image.uri,
type: image.type,
name: "tmpImage",
});
try {
await axios.post(`${BACKEND_URL}/recipes/photo`, {
formData,
header: { "Content-Type": "multipart/form-data" },
});
} catch (error) {
console.error("Error when sending image");
}
and here is my nodejs code
multer conf :
export const storage = multer.diskStorage({
destination: function (req, file, callback) {
console.log("here dest");
callback(null, "uploads");
},
filename: function (req, file, callback) {
console.log("here filename");
callback(null, file.originalname);
},
});
export const upload: any = multer({ storage });
route :
recipesRoutes.post(
"/photo",
upload.single("tmpImage"),
async (req: Request, res: Response) => {
console.log("req files =>", req.files);
console.log("req file =>", req.file);
return res.status(200).send();
}
);
express conf :
app.use(cors());
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
req.file is undefined and I don't understand why.
Thanks for help
I think you need to use the different curly brackets for the data that you are sending
and the headers that you configuring. it must be something like this:
await axios.post(`${BACKEND_URL}/recipes/photo`,
{formData},
{header: { "Content-Type": "multipart/form-data" }},
);
based on this example :
import axios from 'axios';
axios.post('https://httpbin.org/post', {x: 1}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data}) => console.log(data));
on this page
GitHub

Unable to make request in node.js

I am using the following code in the controller by CCAvenue but I get an error
TypeError: request.on is not a function
Below is the code for the request
request.on('data', function (data) {
console.log("data is ----------------> " + data);
body += data;
encRequest = ccav.encrypt(body, workingKey);
console.log("Enc request " + encRequest);
formbody = '<form id="nonseamless" method="post" name="redirect" action="https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction"/> <input type="hidden" id="encRequest" name="encRequest" value="' + encRequest + '"><input type="hidden" name="access_code" id="access_code" value="' + accessCode + '"><script language="javascript">document.redirect.submit();</script></form>';
});
request.on('end', function () {
response.writeHeader(200, {
"Content-Type": "text/html"
});
response.write(formbody);
response.end();
});
I am including the request using var request = require('request')
Edit:
request.post("https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction", {
form: {
encRequest: encRequest,
access_code: accessCode
}
},
function (error, response, body) {
console.log(body);
});
I get a response in my body which is an html page. How do I send it back to the browser in sail.js framework ?
Edit 2 :
I've tried using sails.request method too but there is no response.
var payReq = {
url: "https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction",
method: "POST",
headers: {
"Content-Type": "text/html"
// "Content-Type": 'application/json'
},
// data : {
// encRequest: encRequest,
// access_code: accessCode
// }
data : `encRequest=${encRequest}&access_code=${accessCode}`
}
sails.request(payReq);
I think you're using Request in an incorrect way.. this pattern you're using would work for the HTTP/HTTPS libraries. Here's a Request example.
var request = require('request');
var options = {
url: "https://httpbin.org/ip",
method: "get"
};
console.log('Requesting IP..');
request(options, function (error, response, body) {
if (error) {
console.error('error:', error);
} else {
console.log('Response: Headers:', response && response.headers);
}
});
The request.on('data' .. pattern is used by the Native HTTP and HTTPs libraries. examples would be here:
https://www.twilio.com/blog/2017/08/http-requests-in-node-js.html
This page includes examples using Request, HTTP, Axios.

Render EJS - Node JS

I would like to update my view after an ajax call, rendering compiled ejs from the server.
These two previous questions seem to achieve this but I cannot update my view
Can't Render EJS Template on Client
How to generate content on ejs with jquery after ajax call to express server
So from what I understand I should compile my ejs file (partial) on the server.
fixtures.ejs
<% fixtures.forEach((fixture) => { %>
<h2><%= fixture.home_team %> vs <%= fixture.away_team %></h2>
<% }) %>
index.js
app.post('/league_fixtures', async function (req, res) {
try {
var league_name = req.body.league_name;
const fixtures = await leagueFixtures(league_name);
//compile view
fs.readFile('./views/fixtures.ejs', "utf-8", function(err, template) {
fixture_template = ejs.compile(template, { client: true });
var html = fixture_template({fixtures: fixtures});
console.log(html);
// This logs out my HTML with fixtures so I am almost there
// <h2>Club Africain vs Al-Faisaly Amman</h2>
// <h2>Al Nejmeh vs ASAC Concorde</h2>
});
res.json({fixtures: fixtures });
} catch (err) {
res.status(500).send({ error: 'Something failed!' })
}
});
Ajax
$("a.league-name").on("click", function (e) {
e.preventDefault();
var league_name = $(this).text().trim();
$.ajax({
url: '/league_fixtures',
type: 'POST',
dataType: "json",
data: { league_name: league_name },
success: function(fixtures){
// How do i get HTML from server into here ?
$('#panel_' + league_name).html(fixtures);
},
error: function(jqXHR, textStatus, err){
alert('text status '+textStatus+', err '+err)
}
})
});
});
I don't get any errors when I fire the ajax request but I also do not get any data or HTML updated in my div.
What am I doing wrong?
So I finally got a working solution:
index.js
app.post('/league_fixtures', async function (req, res) {
try {
const league_name = req.body.league_name;
const fixtures = await leagueFixtures(league_name);
const file = await readFile('./views/fixtures.ejs');
var fixture_template = ejs.compile(file, { client: true });
const html = fixture_template({fixtures: fixtures});
res.send({ html: html });
} catch (err) {
res.status(500).send({ error: 'Something failed!' })
}
});
ajax call
$.ajax({
url: '/league_fixtures',
type: 'POST',
dataType: "json",
cache: true,
data: { league_name: league_name },
success: function(fixtures){
var html = fixtures['html'];
$('#panel_' + league_name).html(html);
},
error: function(jqXHR, textStatus, err){
alert('text status '+textStatus+', err '+err)
}
})

Empty Object in req body on post request

I'm having trouble with getting the proper data out of req.body
When I fetch a request to the server I get this in my console (Ex: 'Wash dishes' as the value for the input)
// console log
{}
{ item: 'Wash dishes' }
an empty object first and then the item I specified.
html file
<form autocomplete="off" id="formform" method="POST">
<input type="text" name="item" placeholder="Add new item..." required id="inputinput" >
<button type="submit">Add Item</button>
</form>
test-w-fetch.js
let newForm = document.getElementById('formform');
newForm.addEventListener('submit', (evt) =>{
let item = document.getElementById('inputinput');
let todo = {item: item.value};
fetch('/todo', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: todo
}).then( (response) => {
return response.json();
}).then((data) =>{
location.reload();
}).catch((err) =>{
console.log(`There's an ${err}!!`);
});
return false;
});
Here's my POST route on the server
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.post('/todo', (req, res) => {
// Need to get data from the view and add it to mongodb
console.log(req.body);
let newItem = new Todo(req.body);
newItem.save( (err, data) =>{
if (err) throw err;
res.json(data);
});
});
Other option I have tried was taking error checking req.body.item property, storing it into a new object, and passing it to the database, but the empty object is still going through the body and getting saved to the database
One thing you could try to is use Postman to te to see if the issue is server or client side. Would help narrow down the troubleshooting surface area.

AngularJS Post Request Undefined

I am making a post request to insert comments into my MongoDB database. I am receiving an error 500 when trying to make this insert. I believe this is due to the value not being received when making the request. Where am I going wrong when posting these values?
app.post('/addComment', (req, res) =>{
console.log(req.body.description, typeof(req.body.description));
var com = new Comment({
description: req.body.description,
sentiment: ml.classify(req.body.description),
status: req.body.status,
});
com.save(function(err, insComment){
if(err){
console.log('Error loading data');
}
else{
res.send(insComment);
}
});
});
Controllers.js
exports.CommentController = function($scope, $http){
$scope.addComment = function(){
$http({
method :'POST',
url: '/addComment',
headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'},
data:{
//username:$scope.username,
description: $scope.description,
//sentiment: $scope.sentiment,
status:$scope.status,
}
}).then(function (response){
$scope.user = response;
console.log('DESCRIPTION ' + typeof($scope.description))
//$scope.user = response;
}, function(err){
console.log(err);
})
}
}
$scope.addComment = function(){
$http.post('/addComment', {
description: $scope.review.description,
status: $scope.review.status,
},
{headers: {'Content-Type': 'application/json'}}).
success(function(data){
$scope.user = data;
console.log('DESCRIPTION 2 ' + typeof($scope.description))
console.log(data);
}).error(function(err){
console.log(err);
});
};
Front end
<div class="row p-b-25">
<div class="col-12 p-b-5">
<input type="text"
ng-model="review.description">
</div>
<add-comment></add-comment>
</div>
Please add complete url and try.
e:g
$http({
method :'POST',
url: 'http://localhost:3000/addComment',

Resources