React reloads the page after replacing images - node.js

I am uploading images to a server. If it is present and replaced, then React refreshes the page with a loss of state. How can I stop this behavior?
Node:
let form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
let {size, path, name, type} = files.image,
newpath = pathLib.join(__dirname, '../client/public/uploads') + name;
fs.rename(path, newpath, function (err) {
if(err) throw err;
});
});
React:
<form id="uploadForm">
<input id="uploadInput" name="image" type="file" />
</form>
<span onClick={() => {
let form = document.querySelector("#uploadForm"),
formData = new FormData(form);
if(form.querySelector("#uploadInput").files.length)
uploadFiles(formData, (res) => {
console.log(res.data.errors);
});
}}>Save</span>
An important addition! Page refreshed even without interaction with React components. Replacing an image through the Windows file manager calls the re-render.

Just call event.preventDefault() when submit form. See the example here:
<form id="formSubmit"}>
<input id="uploadInput" name="image" type="file" />
<button type="submit"></button>
</form>
document.getElementById('formSubmit').addEventListener('submit',function(event){
event.preventDefault()
// write here your others code
})

Related

Express function sending multiple times

My react js file is currently like this
export default function Blog() {
const [title, setTitle] = useState('');
const [blog, setBlog] = useState('');
const sumbitBlog = () => {
axios.post('http://localhost:3001/api/insert', {
title: title,
blog: blog
});
}
return (
<div className='container'>
<div className='row'>
<form className='col-lg-12 form-group'>
<div className="form-group">
<label for="formGroupExampleInput">Title</label>
<input type="text" className="form-control"placeholder="Title" name="title" onChange={(e)=>{
setTitle(e);
}}/>
</div>
<div className="form-group">
<label for="formGroupExampleInput2">Body</label>
<input type="text" className="form-control" placeholder="Body" name="blog" onChange={(e) =>{
setBlog(e);
}}/>
</div>
<button className='btn-primary' type="submit"onClick={sumbitBlog()}>Submit</button>
</form>
</div>
</div>
);
}
And my nodejs back end code :
app.post('/api/insert', (req, res) =>{
const title = req.body.title;
const blog = req.body.blog;
const sql = `INSERT INTO posts (title, body) VALUES ("this","works")`;
db.query(sql,[title, blog], (err, result)=>{
if(err) throw err;
console.log(title);
console.log(blog)
});
});
even though it looks right, it keep sending multiple requests
I have I don't know what is happening, I tried using different ways of doing it looking from the internet, but only this way it inserts to the database. any other way it wont even try connecting to it.
the database
Try to pass a reference to the function instead of firing it every time you render it.
So:
onClick={sumbitBlog}
instead of:
onClick={sumbitBlog()}
Your backend function does not send a response back to the client, because it lacks a res.json() function call or similar. If you insert a statement
res.json(result);
after the two console.log statements, the client will receive a JSON response, which you must then use to somehow update the client so that the user can read that the insertion was successful. The following code simply alerts the user and displays the JSON, but you probably want something more elegant.
const sumbitBlog = async () => {
var response = await axios.post('http://localhost:3001/api/insert', {
title: title,
blog: blog
});
alert(JSON.stringify(response.data));
}

Passing Data between app.post to app.get in nodejs

I am fairly new to nodejs and express. I am using nodejs and handlebars to create a simple back end CRUD App. Right now I am stuck on how to pass the value from a form I created in handlebars to an app.get function in my index.js file so inside my app.get function I can use the value to do a database query. After I do the query I want to display the results using app.get and render it to web page.
This is my Handlebars code:
<section id="main" class="wrapper">
<div id="view" class="container">
<section id="main" class="wrapper">
<div id="class" class="container">
<div class="card-body">
<form action="/getid/submit" method="POST">
<div class="form-group">
<label for="id"></label>
<input type="text" class="form-control" id="id" name="id"
placeholder="Enter ID">
</div>
<button type="submit" class="btn btn-primary">Enter ID</button>
</form>
</div>
</div>
</section>
This is the post function in index.js
app.post('/getid/submit',(req,res)=>{
const id = req.body.id;
console.log(id);
res.redirect('page1');
});
This is the app.get function:
app.get('/view/id',(req,res)=>{
//id = ?
var sql = `SELECT * FROM class WHERE Id =${id}`;
db.query(sql,function (err,result){
if(err) throw error;
res.render('page2',{title: 'test', items: rows})
});
});
My main question would be How do I pass the value that I am getting from the app.post form to my app.get function so I can run the query with that ID and render the values to the webpage. THank you in advance.
The id you need to achieve is in request parameters. So you should try:
app.get('/view/:id', (req, res) => {
//id = ?
const id = req.params.id
var sql = `SELECT * FROM class WHERE Id =${id}`;
db.query(sql, function (err, result) {
if (err) throw error;
res.render('page2', { title: 'test', items: rows })
});
});

Node Express upload file with additional data

I am new to Node JS want to create Rest API for Upload Image and facing this issue.
I want to create a post method with multiple files and additional data from inputs. This is my code:
index.js :
app.post('/upload-photos', upload.array('photos'), function (req, res) {
const uploadInfo = req.files.map(file => {
return {
sourceName: file.originalname,
newName: file.filename
};
});
res.send(uploadInfo);
});
My issue is I want to add some form data like (name, address, phone), has anyone else experienced this, please help me.
Thanks.
When using multer additional fields can be accessed through req.body.
app.post('/upload-photos', upload.array('photos'), function (req, res) {
const { name, address, phone } = req.body;
const uploadInfo = req.files.map(file => {
return {
sourceName: file.originalname,
newName: file.filename
};
});
res.send(uploadInfo);
});
In your form:
<form action="/upload-photos" method="post" enctype="multipart/form-data">
<input type="file" name="photos" multiple />
<input type="text" name="name" />
<input type="text" name="address" />
<input type="text" name="phone" />
</form>

How to send a large datauri of an image to express server

I have the daturi of an image which is uploaded from the desktop.I would like to send this data uri to express server so as to save the dataUri in a text file. Since the size of the data uri of the image is quite large I am getting payload too large error which is understandable. I tried using multer but I couldn't figure out how to extract the data uri of the image when multer is used, on the server side.Any help on this is greatly appreciated.
Below is some of the code sample that I am trying to use
<div class="row">
<div class="form-group">
<label class="btn btn-default btn-file" for="FileUpload">Upload a Plan</label>
<input type="file" id ="FileUpload" accept="image/*" capture="camera" value="" onchange="readFileURL(this);" style="display: none;">
<img id="chosenFile" src="#" style="visibility: hidden;"/>
</div>
</div>
<div class="row">
<div class="col-sm-12"><button style="background-color: green" class="btn btn-default btn-sm" onclick="handleUplod(this)">Upload</button></div>
</div>
<script type="text/javascript">
function readFileURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
document.getElementById("chosenFile").style.visibility="visible";
reader.onload = function (e) {
$('#chosenFile').attr('src', e.target.result).width(150).height(150);
console.log("result:",e.target.result);
imageData = e.target.result;
};
console.log("data url:"+reader.readAsDataURL(input.files[0]));
}
};
function handleUplod(){
$.ajax({
type: "POST",
url: "/send",
data: { MyPlanDataUri:imageData },
success: function(result){
location.href= "/someplace";
},
error: function(result) {
alert('error');
}
});
};
On the server side I am doing the following
app.post('/send', function(req,res) {
var Tex1 = req.body.MyPlanDataUri;
var newFile = "ImageFile.txt";
fs.writeFile(newFile, Tex1, (err) => {
if (err) res.send(err);
console.log('File saved successfully ! - ', newFile);
}
);
res.send("Successfull");
}
P.S the above code works perfectly fine for small datauri's

post input type file to server node.js from angular service call

I have simple multipart formdata
<form action="/upload" enctype="multipart/form-data" method="post">
<span class="btn btn-file">
<input type="file" name="file" ng-model="file"/>
<span class="btn btn-primary" ng-click="upload()">Upload</span>
</span>
</form>
What I want to do it, post all the information related to file to the server written in node.js
server.js This is file upload handler written in node. Formidable expects all parameters of a file.
upload: function uploadfn (req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
// `file` is the name of the <input> field of type `file`
var old_path = files.file.path,
file_size = files.file.size,
file_ext = files.file.name.split('.').pop(),
index = old_path.lastIndexOf('/') + 1,
file_name = old_path.substr(index),
new_path = path.join(process.env.PWD, '/uploads/', file_name + '.' + file_ext);
fs.readFile(old_path, function(err, data) {
fs.writeFile(new_path, data, function(err) {
fs.unlink(old_path, function(err) {
if (err) {
res.status(500);
res.json({'success': false});
} else {
res.status(200);
res.json({'success': true});
}
});
});
});
});
}
The things I'm stuck at is, I have service call ready in angular as follows:
service.factory('FileUpload', function ($resource) {
return $resource('/upload', {}, {
post: {method: 'POST'}
});
});
This call hits the backend from angular controller as follows
$scope.upload = function(){
console.log($scope.file);
FileUpload.post(function(){
});
}
I'm not sure how to post the file submit so that node can catch it. Also $scope.file is undefined.
Please help me solve this.
There's a good directive for file upload for angularjs, try to use it
https://github.com/danialfarid/angular-file-upload

Resources