Uploading file from form to server - javascript

I am currently working on a dashboard, and have been stuck for some couple of hours now... What I like to do is to have a form including 3 <input type="file"> (two of them allow multiple files, one not), and each of them posting to 3 different post-methods in the server. When I try to console log the request on the server side the data is empty ({}) . I do not understand why, can someone please help me solve this issue?
I am using angularjs, and nodejs btw.
This is what my current code is : (files and paths are dummy-names)
HTML:
<form role="form" enctype="multipart/form-data">
<div class="form-group">
<label for="file1">File1:</label>
<input type="file" id="file1" accept=".txt, .json" multiple>
</div>
<div class="form-group">
<label for="file2">File2:</label>
<input type="file" id="file2" accept=".json">
</div>
<div class="form-group">
<label for="file3">File3:</label>
<input type="file" id="file3" multiple>
</div>
<button type="button" ng-click="save()" class="btn btn-default"> Save</button>
</form>
JS:
module.exports = function($scope, $http) {
$scope.save = function () {
file1(document.getElementById('file1').files);
file2(document.getElementById('file2').files);
file3(document.getElementById('file3').files);
};
function file1(files) {
$http.post('/file1', {f: files}).success(function (res) {
//todo
});
};
function file2(files) {
$http.post('/file2', {f: files}).success(function (res) {
//todo
});
};
function file3(files) {
$http.post('/file3', {f: files}).success(function (res) {
//todo
});
};
}
Server.js
var express = require("express"),
fs = require("fs"),
bodyParser = require('body-parser'),
app.use(express.static("build"));
app.use(bodyParser());
app.post('/file1', function (req, res) {
console.log(req.body.f) // returns empty: {}
// like to move files to path: a/b/c
});
app.post('/file2', function (req, res) {
// like to move files to path: a/d/e
});
app.post('/file3', function (req, res) {
// like to move files to path: a/f/g
});
Update:
after receiving the answer from GrimurD, I have modified the server.js, but still struggling. Any takers?
var express = require("express"),
fs = require("fs"),
bodyParser = require('body-parser'),
multer = require('multer'), //<-- updated
upload = multer({ dest: './uploads/' }) //<-- updated
app.use(express.static("build"));
app.use(bodyParser());
app.use(multer({ dest: './uploads/' }).array()); // <-- updated
app.post('/file1', upload.array('file1'), function (req, res) {
console.log(req.body.f) // returns empty: {}
console.log(req.files); // returns undefined // <-- updated
// like to move files to path: a/b/c
});
app.post('/file2', upload.single('file2'), function (req, res) {
console.log(req.file); // returns undefined // <-- updated
// like to move files to path: a/d/e
});
app.post('/file3', upload.array('file3'), function (req, res) {
console.log(req.files); // returns undefined // <-- updated
// like to move files to path: a/f/g
});

When uploading a file the form must use multipart/form-data which body-parser doesn't support. You must use a specialized middleware to handle this type. Multer is one such that I have used with success.

You can get around this using FileReader.readAsDataURL(..) on the File objects in the input fields. I often like to use the multi-select ability on the file input type so that I can upload a bunch of files and do this async.
So what I normally do is access the files property on the input element and loop through them, then I use the FileReader.readAsDataURL to get the base64 of the binary for the files then passing the base64 to a webserivce method with a signature that accepts that a string param for the base64, convert the b64 to binary and you're back in business.
var fileRunner = {
files: [],
run: function(el) {
this.files = el.files;
this.read();
},
read: function() {
// begin the read operation
console.log(this.files.length);
for (var i = 0; i <= this.files.length - 1; i++) {
var reader = new FileReader();
reader.readAsDataURL(this.files[i]);
reader.onload = this.process
}
},
process: function(evt) {
var result = evt.target.result
if (result.length > 0) {
var parts = result.split(',')
var dataBsf = parts[parts.length - 1];
console.log(dataBsf);
//call method to pass the base 64 here.
}
}
};
<body>
<input id="fup" type="file" multiple="multiple" onchange="fileRunner.run(this)" />
</body>
I did not include a server side component to this because I think that should be agnostic and slightly out of scope here.
I am only logging the output to the console, but you would take the output and pump it to the web service.
Additionally, I referenced the input element in the event handler for the onchange using "this" because I had no idea how you wanted to handle it. Allowing the passing of an element provided a bit of loose assumptions on my part.

Related

Save HTML form data to text file using node js

I am using node js and my requirement is save HTML form values which is sent by user, and store those values in text file using node js, and each time data should be save to next lines instead of saving to same line.I got stuck how to do this process.
HTML Code:
<form method="POST" action="/users/contact">
<select name="car" size="1" required id="rankx">
<option value="" selected disabled hidden>Option</option>
<option value="volvo">volvo</option>
<option value="swift">swift</option>
</select>
<br />
<select name="model" size="1" required>
<option value="" selected disabled hidden>Rank</option>
<option value="c500">c500</option>
<option value="Ta66">Ta66</option>
</select>
<input type="submit" value="Submit" name="submit" id="submit"/>
Node js Code:
var express = require('express');
var fs = require ('fs');
router.post("/contact",function(req,res){
let car = req.body.car;
let model = req.body.model;
var form_data = {
car: car,
model: model
}
fs.appendFileSync('./message.txt',form_data.toString());
});
Required outpt: // store in text file userData.txt
id carname carmodel
1 abc abc_1
2 xyz xyz_1
The solution what happens to me was first create a JSON file to save the data and next put this information in a text file. Following four steps:
Step 1: First you need read the existing data from JSON file.
Step 2: Add new car using push method.
Step 3: Write the new and old data in JSON file.
Step 4: Write the new info in the a text file.
Here is the code:
app.js
const express = require('express');
const app =express()
var fs = require ('fs');
// middleware
app.use(express.urlencoded({extended:true}))
// STEP 1: Read the existing data from json file
let users= require("./message.json")
// API routes
app.get('/', (req, res) => {
res.sendFile(__dirname + '/public/index.html');
})
app.post("/",function(req,res){
let car = req.body.car;
let model = req.body.model;
// new car
let formData = {
car: car,
model: model
}
res.send(formData)
// STEP 2: add new user data to users object using push method
users.push(formData)
// STEP 3: Writing data in a JSON file
fs.writeFile('message.json', JSON.stringify(users), err =>{
if(err) throw err
console.log("Done writting JSON file")
})
// STEP 4: Write the new info in the text file named message
fs.writeFile('./message.txt',JSON.stringify(users), err =>{
if(err) throw err
console.log("Done writting text file")
});
});
app.listen(3000, function(){
console.log("server started on port 3000")
})
You need create a JSON file to save data like this:
message.json
[]
and a empty message.txt to storage the data, this file overwrite when save the data.
Leave screenshots.
I hope help you.

How to receive data from a button in a form?

This seems very simple but I can't figure it out. I am trying to get back the value of a button so I can conditionally render a page template. I can't seem to capture the value of the button though.
Here is my js code.
app.get("/trades", (req, res) => { // line 465
let button_value = req.params.value;
console.log(button_value);
// res.render("activate_pause")
});
And here is my html/ejs markup:
<form action="/trades" methods="get, post" name="groups_button">
<button class="orange" type="submit" name="frontpage_trades_button" value="pause">Pause Campaigns</button>
<button type="submit" name="frontpage_trades_button" value="enable">Activate Campaigns</button>
</form>
The values 'pause' or 'enable' will be used to set a status of true or false, which will render the desired template ( or so I hope!). Can anyone help??
methods is not a valid attribute of the <form> element
console.log('Is method in <form>?: ', 'method' in HTMLFormElement.prototype);
console.log('Is methods in <form>?: ', 'methods' in HTMLFormElement.prototype);
So the first thing to do is to replace methods with method and set only one method (I'd suggest POST).
Then in the Node.js code, make sure you have the proper middleware in order to decode URL encoded forms:
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
This should allow you to retrieve the value of the clicked button, like this:
app.post("/trades", (req, res) => {
let button_value = req.body.frontpage_trades_button;
console.log(button_value);
// res.render("activate_pause")
});
u can use data attribute to take it
<button type="submit"id="x" name="frontpage_trades_button" data-value="enable">Activate Campaigns</button>
app.get("/trades", (req, res) => { // line 465
let button_value = req.params.value;
console.log($("#x").data("value"));
// res.render("activate_pause")
});

Trigger .py file when JS page is opened on nodjs server browser

I have a nodjs server set up with several JS pages. On one of them, I want a local .py file to be opened and run one time in the background. I DON'T need to generate a response from it.
I have flask set up already, but I don't understand how to incorporate that with my current React Javascript page (the one I want my python file triggered from).
In different instances, I have tried using:
var path = require('C:/Users/myPath/python.exe');
var nwDir = path.dirname(process.execPath);
var spawn = require("child_process").spawn;
var child = spawn(nwDir + '/test.py');]
as well as:
const spawn = require("child_process").spawn;
const pythonProcess = spawn('python',["/test.py"]);
but I receive this error in both instances:
TypeError: spawn is not a function
located at:
const pythonProcess = spawn('python',["/test.py"]);
lastly I have also tried:
var express = require('express');
var app = express();
const {PythonShell} = require('python-shell');
var options = {
mode: 'text',
pythonPath:
'C:/Users/myPath/python.exe',
pythonOptions: [],
// make sure you use an absolute path for scriptPath
scriptPath:
C:/Users/myPath/test.py', args: []
};
PythonShell.run('test.py', options, function (err, results) {
if (err) throw err;
// results is an array consisting of messages collected during
execution
console.log('results: %j', results);
});
but I receive this error:
TypeError: Cannot read property 'prototype' of undefined
located at my response.js file:
var res = Object.create(http.ServerResponse.prototype);
Is there something I should be including in my server.js file?
Is there a way I can incorporate flask with my current JS page?
For reference, here is a basic version of my current JS file:
myFile.js:
import React from "react";
import Header from "../Header";
import Footer from "../Footer";
class SummaryPage extends React.Component {
render() {
return (
<div>
<Header />
<div className="container-fluid ">
<b><h1>Update and Read CSV File </h1></b>
</div>
<form enctype="multipart/form-data" action="/upload/image"
method="post">
<input type="file" id="fileUpload" />
<div id="dvCSV">
</div>
</form>
<Footer/>
</div>
);
}
}
export default SummaryPage;
To reiterate, how can I have a local .py file be opened and run in the background when my JS page is opened? I would also be happy if it had to occur with the click of a button. No response from the .py file is needed.
Thank you for the time.

ReCaptcha validation on Node.js

on my express server, g-recaptcha-response always return nothing. This is my code at the moment:
<div class=container-fluid id=mcenter>
<form id='monitstart' action="/monitstart" method="POST">
<input type="text" class="form-control" aria-label="..." name=>
<button class="g-recaptcha" data-sitekey="SITEKEYHERE" data-callback="onSubmit"></button>
</form>
</div>
and on my server
var express = require('express')
var router = express.Router()
var request = require('request')
router.post('/monitstart', function (req, res) {
request({url: "https://www.google.com/recaptcha/api/siteverify?secret=SECRETHERE&response=" + req.body['g-recaptcha-response']} + '&remoteip=' + req.connection.remoteAddress, function (err, response, body) {
req.send(body)
})
})
module.exports = router
And when I try to validate it, it give me a code 500 and say TypeError: Cannot read property 'g-recaptcha-response' of undefined
The correct answer, accepted by the OP during the short discussion below the question involves adding the body parsing middleware (the body-parser) to the pipeline so that the body property of the request object is correctly initialized before a value is read from there.

Sails.js req.files is empty and req.body.image is undefined

I've been trying to understand this since yesterday but I can't find any solutions, even by asking Google and StackOverFlow.
The problem is that I'm building a project inside which I have "Product" Model, Controller, and Views. On the new.ejs view, I have a form which contains a file tag (named image). So, on the controller, I try to get the image path by logging req.files.image.path in the console but req.files is empty. I also tried to display req.body.image which is undefined.
Here is the client-side code (views/product/new.ejs) :
(This is a Sails.js app)
Here is the client-side code (views/product/new) :
<div class='container'>
<form action='/product/create' role='form' class='form-signin' enctype="multipart/form-data" id='product-form'>
<div class='form-group'>
<label class='sr-only' for='name'>Name of the product</label>
<input type="text" class='form-control' placeholder="Name" name='name' id='name' />
</div>
<div class='form-group'>
<label class='sr-only' for='image'>Image of the product</label>
<input type="file" name='image' id='image' />
</div>
.
.
.etc...
and here is the server-side (api/controllers/ProductController.js) :
'create': function(req, res, next) {
// Include the node file module
var fs = require('fs');
console.log(req.files); //This logs : { } in the console
console.log(req.body.image); //This logs : undefined in the console
//Readfile with fs doesn't work cause req.files is empty
// fs.readFile(req.files.image.path, function(error, data) {
// //get image name
// var imageName = req.files.data.name;
// //if enable to get name
// if (!imageName) {
// console.log('error uploading image');
// res.redirect('/product/new');
// //Else if we have an image
// } else {
// //change the path to our own
// var newPath = __dirname + '/assets/images/products/fullsize/' + imageName;
// fs.writeFile(newPath, data, function(error) {
// console.log(newPath);
// //res.redirect('/product' + imageName);
// });
// }
// });
}
Thanks for your help.
Mat.
Also available here : https://github.com/balderdashy/sails/issues/1127
use method=post in your html form

Categories