I am currently developing a website where I need to upload multiple image files. To accomplish this, I am using blobs to upload the files to the server. It works fine when I upload a single file, but I encounter an error when I try to upload more than two files.
I have defined the state like this:
type BlobNull = {
0: Blob | null
1: Blob | null
2: Blob | null
3: Blob | null
}
const [blobs, setBlobs] = React.useState < BlobNull > ({
0: null,
1: null,
2: null,
3: null,
})
const [catalog, setCatalog] = React.useState({
ProductName: "",
cShopVisiblity: true,
Delivery: true,
ItemPrice: "",
Quantitiy: "",
Notes: "Notes"
})
I use a handler function for submitting:
const handleAdd = async () => {
startLoading();
try {
if (Object.values(catalog).every(val => val.toString().trim() !== "")) {
const formData = new FormData();
Object.keys(catalog).forEach(key => formData.append(key, catalog[key]));
Object.values(blobs).filter(val => val !== null).forEach((blob, id) => formData.append(`Img`, blob))
const { data, isOK } = await catalogService.add(formData);
if (isOK) {
addToastMsg(`Details saved : ${data.ProductName} ${data.Quantitiy}`, "success");
setCatalog({
ProductName: "",
cShopVisiblity: true,
Delivery: true,
ItemPrice: "",
Quantitiy: "",
Notes: "Notes"
});
setOpen(false);
} else {
throw new Error("Internal server error");
}
} else {
addToastMsg("Please fill all the fields required.", "warning");
}
} catch (e) {
console.error("error saving form", e);
addToastMsg(
"Unable to save details, please re validate entered values",
"error"
);
}
endLoading();
}
exports.add = async (req, res) => {
try {
// if (req.file) console.log("file");
// if (req.files) console.log("files");
// if (req.Img) console.log("Img");
// if (req.data) console.log("data");
if (req.files?.length > 1 && Array.isArray(req.files['Img'])) {
multiUpload(req, res, async function (err) {
if (err) {
return res.status(400).json({ message: 'Error uploading files' });
}
const files = req.files;
const imageBuffers = files.map((file, id) => ({ [`Img${id > 0 ? id : ''}`]: Buffer.from(file.buffer) }))
const catalog = await catalogsModel.create({ ...req.body, ...imageBuffers });
res.status(201).json({
success: true,
data: catalog,
});
});
} else {
singleUpload(req, res, async function (err) {
if (err) {
// handle the error here
return res.status(400).json({ message: 'Error uploading file' });
}
if (req.file) {
const imageBuffer = Buffer.from(req.file.buffer);
const catalog = await catalogsModel.create({ ...req.body, Img: imageBuffer });
res.status(201).json({
success: true,
data: catalog,
});
} else {
const catalog = await catalogsModel.create(req.body);
res.status(201).json({
success: true,
data: catalog,
});
}
// fs.writeFile(`./uploads/${file.originalname}`, file.buffer, function (err) {
// if (err) {
// // handle the error here
// return res.status(500).json({ message: 'Error saving file' });
// }
// // return a success response
// return res.status(200).json({ message: 'File uploaded successfully' });
// });
});
}
} catch (error) {
console.log("API error", error);
if (!res.headersSent) {
res.send(500).json({
success: false,
error: "Server error",
});
}
return;
}
};
In the above code, 'blobs' is the state for the image data blob. It has been properly configured and works well.
However, on the server side, when I check if multiple files were uploaded, it returns all undefined.
As you can see in the code, if I uncomment and log the properties of the 'req' variable, it outputs undefined.
What could be the issue?
What is interesting here is that uploading a single file works well. Only uploading multiple files causes issues.
I think I can answer this question. I searched and searched the whole time for an error regarding to api response. The issue was the "propertyName" on user endpoint in the nuxt.config.js. It is set to "user" as default. When I set it to "propertyName: false", than everything works as it should. By default, the "propertyName" is set to "user", which expects the response from the "/user" endpoint to have a property named "user" containing the user data. However, in your case, it seems that the response does not follow this structure, so setting "propertyName: false" bypasses the property assignment.
auth: {
strategies: {
local: {
endpoints: {
login: {url: '/login', method: 'post', propertyName: 'token' },
user: {url: '/user', method: 'get', propertyName: false },
logout: false,
}
}
}
},