Reputation: 1498
I in my React app I send a request containing a JSON body with various fields, among which is an array of File
type images.
const body = {
title: 'title',
price: 100,
images: [...]
};
axios.post(url, body);
This doesn't work and the images
array arrives at the Express app empty.
I have consulted the internet and have tried using FormData
. However, all the solutions I saw (example) only have images in them, i.e.
const images = [...];
const data = new FormData();
images.forEach(img => data.append(img.title, img));
But I want the entire thing - the text and the images, because this input is supposed to go into MongoDB.
I have tried simply putting the entire object in a FormData
:
const data = new FormData();
data.append('body', body);
But I must not understand how FormData
actually works because trying to iterate over the req.body
over in Express just yields nothing:
app.get((req, res) => {
const data = Object.fromEntries(req.body) // yields nothing
}
Any other attempts like using multer
reinforce that I'm doing something wrong, because I cannot for the life of me get a non-empty request body.
What I want to do is to be able to send a full HTTP body of data that includes text, numbers, and an array of images, such that over on the Express app I could save those images to disk. Any nice suggestions would be appreciated.
Upvotes: 0
Views: 1383
Reputation: 106
You cannot use json to send images(not the original file), but there's an option with form data. First, you have to separate the files from the normal data, and parse the normal data to a string.
const images = [...];
const body = new FormData();
// you have to put the images in the same field, and the server will receive an array
images.forEach(img => body.append('images', img));
// the other data to send
const data = {
someData: true,
moreData: 1,
arrOfNormalData: [23,10];
}
const parsedData = JSON.stringify(data);
body.append('_jsonData', parsedData);
axios.post(url, body);
You are sending the json data as string in the _jsonData
field of your request.
Then en your node server, you have to install multer on configure it ej
const path = require('path');
//this is for a random id for file name
const { nanoid } = require('nanoid');
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads')
},
filename: function (req, file, cb) {
cb(null, nanoid() + path.extname(file.originalname));
}
})
const upload = multer({ storage: storage });
Then you have can create a middleware to parse the data (remember we converted it to a string) to a object.
const parseJson = (field = '_jsonData') => {
return (req, res, next) => {
if (req.body[field] && typeof req.body[field] === 'string') {
req.body = JSON.parse(req.body[field]);
}
next();
};
};
Then lets use in in our route
app.get(upload.array('images',10),parseJson(),(req, res) => {
const data = req.body;// here the json data
const files = req.files;// here the uploaded files
}
We have added the upload.array('images',10)
where images
is the field of files and 10
is the max number of files
We added our parseJons middleware to parse the string to json
Don't use base64, you can have issues if you are working with base64. Use formdata
Upvotes: 1