this is Omar,
Note: Too much talk? the sections below not all of them is a must to check if you are just trying to understand the problem, just see these ones:
- Front End (A really quick look at the code)
- Back End (You can check if you want, but it is just standard setup for multer)
- Postman (A quick look at request details, and dont look at its code)
- Network tab (Check it)
- What Happened in the Backend (understand the problem)
Front End
my problem is when sending FormData
using fetch in my front-end (react):
const formData = new FormData();
formData.append('file', values.image);
formData.append('path', 'image');
formData.append('model', 'item');
formData.append(
'data',
JSON.stringify({
menu: menu._id.toString(),
item: values.item,
})
);
const req = new Request(`/api/v1/upload`, {
method: 'POST',
body: formData,
});
The Request
constructor is the exact same as fetch, but it just skips doing response.json()
everytime, Request class is my own (I built it)
Back End
Backend code is using multer for multipart formData.
Backend perfectly works fine with postman, so using postman to send the request works just fine, but using fetch as up does not.
for the backend code, it is just simple, i use upload.single, and memoryStorage.
Code:
const storage = multer.memoryStorage();
const upload = multer({ storage, fileFilter });
exports.processImage = (req, res, next) => {
if (!req.file) return next();
req.file.filename =
req.modelController.createFileName(req, req.file) + '.jpeg';
sharp(req.file.buffer)
.toFormat('jpeg')
.toFile(
path.join(
`public/image/upload/${req.body.model.toLowerCase()}`,
req.file.filename
)
);
next();
};
Again it works fine if i use postman
Postman
Postman request image
Postman code is really similar to my code:
const formdata = new FormData();
formdata.append("model", "item");
formdata.append("path", "image");
formdata.append("data", "{"menu": "673e442bae0dd4717f4af4c1", "item": "673f76230fb7a35ddfc2cd57"}");
formdata.append("file", fileInput.files[0], "/C:/Users/LENOVO/Downloads/Matrix-Cola-Carbonated-Drink.jpg");
const requestOptions = {
method: "POST",
headers: myHeaders,
body: formdata,
redirect: "follow"
};
fetch("http://127.0.0.1:5423/api/v1/upload/", requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
What Happens in the Backend?
It receives the body as null Object, even using multer, and the file as undefined
Network Tab
network tabs shows the following
Network tab, request payload
Headers are going well, content type is multipart/form-data.
What did i try?
I did not try many things, but:
Content type
Setting the content type header is done automatically by form data instance
What is Values.image?
it is [Object File]
What form do i use
i use formik to handle forms.
but am sure that the file is being saved at values.image
2
Answers
I've solved the CASE!!
For anyone who is getting this problem, please follow these EASY steps:
Steps:
-Check if you have the same thing as i do: My problem wasnt that backend does not receive the
formData
, the problem was thatfileFilter
does not receiveformData
, becausemulter
does not offerreq.body
norreq.file
with it, how to check if that is your problem? go tofileFilter
function, and log thebody
, and then go toprocessImage
function and log the body, if it logs inprocessImage
, but not infileFilter
, then you have my problem, if it doesnt log for both, I dont think that my solution will work for you-How to solve this problem? go to your front-end, appending data like this:
formData.append('file', values.file);
formData.append('textContent', 'textContent');
will not work, you must make the append function forfile
field at the end, as below:formData.append('textContent', 'textContent');
formData.append('file', values.file);
And your problem have been solved. Congrats!Why does this problem happen?
simply because postman sends the data of the form as one piece, and the file field is at the end, while front end, you made file field first, so while
multer
process the file field, it runsfileFilter
, sofileFilter
does not gets the body, nor the file, while when sending body first then file, the body gets processed, sofileFilter
Thanks for everyone. By the way this case is answered before, but people who gets into this problem does not know that this is same problem as this.Your frontend code using Request is closely related to fetch because the Request object is designed to be used with the Fetch API. The Request class itself doesn’t perform the actual network operation—it simply creates a Request object that you typically pass to fetch.
The problem arises because your backend isn’t correctly receiving the multipart FormData payload when using
fetch
.The issue is related to the Fetch API because your custom Request class likely wraps it. The root cause is the handling of the Content-Type header and how FormData is passed. You can resolve this by ensuring the Request class or fetch is used correctly or by switching to a library like axios for consistency.
axios.post
inspects the FormData and sets the Content-Type header with the appropriate boundary (a required part of the multipart/form-data format).This ensures the server correctly interprets the form data.
Demo
server.js
Dependency Install for server
In frontend
App.js
Dependency Install
Result
node server.js
npm start
Postman
Updating step by step
0. Checking npx version and others
1. Create Frontend
result
checking by tree2. Install axios
result
thepackage.json
3. Replace App.js with my code
4. Run server.js
5. Run frontend
At
frontend
directory6. Got response from server
Update 2 using
Request()
Result
: Same result using "Request()"