I am using react as my frontend and express.js as my backend. I new to both framework. I have a component called Papers and I am trying to first upload some documents to the backend server through fetch post then perform some operation on the server side and then I am trying to get back the result from server in the same handler. My code for the handler looks like this:
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
});
// the second fetch would crash the app.
/*fetch('/file_upload').then(function(data){
return data.json();
}).then( json => {
this.setState({
papers: json
});
console.log(json);
});*/
}
My express backend code for the get method is :
app.get('/file_upload', function(req, res){
// testing
res.send({name:"lol"});
});
The problem right now is the second fetch would crash the express app. Since I am new to react and express, can someone please give me some hints if I am doing this in the right way? Thanks!
link to server code: https://github.com/kaiwenshi/learn-webpack/blob/master/src/server/index.js
Express code should look like this if you want to do a POST:
app.post('/file_upload', function(req, res){
// testing
res.send({name:"lol"});
});
And you only need to do one call of fetch. The response ({name: 'lol'}) will be in the promise:
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
}).then(function(data){
return data.json();
}).then( json => {
this.setState({
papers: json
});
console.log(json); // logs {name: 'lol'}
});
}
Related
I have a data object containing strings, booleans, arrays, objects and even Blobs like this:
Now I want to send this object to my Node.js server...
Using traditional fetch API or Ajax I'm unable to send the blobs and they appear like an empty object server side!
I tried to use fetch API even using FormData approach like:
Client:
const fd = new FormData();
fd.append("upload", data); // data is the object to send
fetch('/mother/new-card', {
method: 'post',
body: fd,
})
Server:
controller side:
router.post('/new-card', newCard);
function newCard(req, res) {
motherService.newCard(req)
.then(result => res.json(result))
.catch(err => {
console.log(err);
res.json(err)
});
}
Service side:
async function newCard(req) {
console.log('req.body', req.body);
return { success: req.body }
}
I usually get undefined trying above methods ...
Is there any valid way to send an object with blobs in it?
I have an application, where I need to send the form data through XMLHttpRequest. When I send that information over, I then need to validate the form, then send information back to the client based on if the form validates or not. I'm using nodejs with express.
My client side code is:
editor.save().then((output) => {
let formData = new FormData();
const xhr = new XMLHttpRequest();
formData.append('name', document.getElementById('inputProductName').value);
xhr.open('post', '/items/add', true);
xhr.send(formData);
}).catch((error) => {
console.error('Error: ' + error);
return;
}).finally(() => {
// This is where I need to retrieve the validation code and redirect accordingly.
if (success == false) {
window.location.href = '/items/add/failed';
} else {
window.location.href = '/items/add/success';
}
});
My server side code is this:
router.post('/add', (req, res) => {
let form = new formidable.IncomingForm();
form.parse(req, (err, fields, files) => {
if (fields.name.length < 1) { // If the name is empty
res.status(200).json({
success: false,
message: 'Product name must be specified'
});
} else {
res.status(200).json({
success: true,
message: 'Product added successfully'
});
}
});
});
So if the the validation fails, then I want to be able to get the success and message variable through the client end if possible.
Have a look at using fetch API from MDN docs
fetch data via POST
await response
based on response.success act accordingly
Additionally,looking a the server-side code, it doesn't appear necessary that form encoding be used.
Suggest sending the data in json format and have the server check the request.body for the appropriate field to be populated.
pseudo code
editor.save().then(async (output) => {
let formData = new FormData();
formData.append('name', document.getElementById('inputProductName').value);
const response = await fetch(url, {
method: 'POST',
// ... additional form data here, looks like you can send JSON, no need for form encoding
}
if(response.success) {
window.location.href = '/items/add/success';
} else {
window.location.href = '/items/add/failed';
}
}).catch((error) => {
console.error('Error: ' + error);
return;
})
Note that the anonymous function () => {} is now async () => {} to allow await on the fetch call.
async / await
For this I'm using express.js, react, with the help of form-data.
No matter what I try, when I send a file from the frontend to the server, the server always says it's undefined.
In react, the code is as follows:
onSubmit = () => {
const url = '../api/products/file';
const formData = new FormData();
formData.append('file', this.state.file)
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
console.log(formData);
axios.post(url, formData, config)
.then(res => {
console.log(res.statusText)
})
}
I know the computer has the file because this.state.file returns all the relevant info on the file.
For reference, in the console.log(formData) line, I receive this in the console.
In express, the code is as follows:
router.post('/file', (req,res) => {
console.log("FILE");
console.log(req.file);
console.log(req.body);
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
return res.status(500).json(err)
} else if (err) {
return res.status(500).json(err)
}
return res.status(200).send(req.file)
})
});
My problem here is that my req.file returns 'undefined' whereas my req.body returns {} which indicates that the file isn't even making its way to the server. I'm thinking that either the file isn't going to the form-data properly through appending or it's somehow getting lost on the way to the server which I think is highly unlikely. I've looked over every line of the request of Axios and there's no details on the files within.
I am building my web app on NextJS NodeJS and Express, I am running two servers on localhost 3000 for next and 9000 for express.
I have a form with two input fields and I am sending the state with axios post to the url with data, on the server-side I am receiving that request and sending back the same received data as a response.
I get the response from server with data: success and my data in config.data
Why is my data in config data and how can I get it out from this JSON so I can pass it to a variable.
As for grabbing the data from the config.data, I have tried for loops but they either push 56 elements of 56 numbers to the empty array or don't do nothing.
Client side:
state = {
bank_name: '',
account_number: ''
}
...
onSubmit = (e) => {
e.preventDefault()
axios.post('http://localhost:9000/api/bank', {
bankName: this.state.bank_name,
accNumber: this.state.account_number
})
.then(res => {
console.log(res)
}).catch(err => console.log(err))
}
Server side:
router.post('/', (req, res) => {
const {reqData} = req;
res.send(reqData);
})
Console log from client side ( console.log(res) ):
{
config: {
url: "http://localhost:9000/api/bank",
method: "post",
data: '{"bankName":"some new bank","accNumber":"39276542934235"}'
},
data: "success",
headers: "...",
request: "...",
status: 200,
statusText: "OK",
__proto__: Object
}
...
When I target res.config.data.bankName I get undefined.
I believe this has to do with the server response being as it is, or not parsing the data server receives in the first place, or it is due to promises.
Any input would be helpful, thanks
That res.config.data is string so parse it first JSON.parse(res.config.data) and then access the bankName.
Also you must be using body-parser at the express end. And so post data resides in req.body you should send that back not the whole req IMO.
Express:
router.post('/', (req, res) => {
const reqData = req.body;
return res.send(reqData);
});
Axios: (returned data should be in res.data)
axios.post('http://localhost:9000/api/bank', {
bankName: this.state.bank_name,
accNumber: this.state.account_number
})
.then(res => {
console.log(res.data);
}).catch(err => console.log(err))
}
I want to upload the file from front end developed in React and get that uploaded file inside Express js.
Below is the code snippet of React side when I am uploading the file :
handleUploadFile(ev) {
ev.preventDefault();
var a6 = "File";
const data = new FormData();
data.append('file', this.uploadInput.files[0]);
data.append('fileName', a6);
fetch('http://localhost:4000/api/addDcuments/upload', {
method: 'POST',
body: {data},
json: true,
headers: { "Authorization": cookie.load('userToken') }
}).then((response) => {
response.json().then((body) => {
this.setState({ imageURL: `http://localhost:4000/${body.file}` });
});
});
}
In above code, I have taken the form and called handleUploadFile function on it's onSubmit event.
Now, below is my backend express js code on which I am getting the uploaded file:
export function uploadDocument(req, res, next) {
console.log(JSON.stringify(req.body));
let imageFile = req.files.file;
var ext = path.extname(imageFile.name)
if(imageFile.mimetype == "application/pdf" ||imageFile.mimetype == "application/octet-stream"){
imageFile.mv('D:/React Workspace/React-videos-example/file_path/'+req.body.filename+ext, function(err) {
if (err) {
return res.status(500).send(err);
}
res.json({file: `public/${req.body.filename}.pdf`});
});
}
}
In above code, when I am trying print the req.body, it is returning "{}" as well as I am getting one error:
TypeError: Cannot read property 'file' of undefined.
So, my backend function has been called, but not able to getting that uploaded file. So can anyone have any solution or any reference link for this issue?
When using formdata, you can't use type json in your POST, it needs to be:
contentType: 'multipart/form-data'
instead of "json: true".