I am creating the backend server for a ecommerce website. I handle file uploads with multer and store them in gridfs. Now, when updating a new product, not all images may be submitted to be updated. I need a way to identify what field was updated, so I can delete the current file and upload the new file to mongodb. I've reached the point where I think it's impossible, but I'm still trying. Are there any alternative approach I could take. All responses are greatly appreciated.
Here is the code for the router and the 3 middleware functions I call when a request is made to said route.
```
router
.route("/:id")
.put(
productController.readPhotos,
productController.appendPhotoOnRequestBody,
productController.updateProduct
)
exports.readPhotos = upload.fields([
{ name: "coverPhoto", maxCount: 1 },
{ name: "colorPhoto", maxCount: 4 },
]);
exports.appendPhotoOnRequestBody = asyncHandler(async (req, res, next) => {
req.addedFiles = [];
if (
req.originalUrl === "/api/products" &&
req.method === "POST" &&
!req.files
) {
// Error message to send to user if the above condition is true.
const message = `To create a new product, a coverPhoto and at least one color with a colorPhoto must be specified`;
return next(new AppError(400, message));
} else if (!req.files) next();
if (req.files?.coverPhoto) {
// Extract coverPhoto
const [coverPhoto] = req.files.coverPhoto;
// Process images
const coverPhotoBuffer = await processImage(coverPhoto.buffer, [300, 300]);
// Pushing the coverPhoto to the db
const coverPhotoStream = Readable.from(coverPhotoBuffer);
const coverPhotoValue = await pushToDbFromStream(
coverPhotoStream,
req,
coverPhoto
);
req.body.coverPhoto = coverPhotoValue.filename;
req.addedFiles.push(req.body.coverPhoto);
}
if (req.files?.colorPhoto) {
// Extract colorPhotos
const colorPhotos = [...req.files.colorPhoto];
const colorPhotoBuffers = await Promise.all(
colorPhotos.map((photo) => processImage(photo.buffer, [50, 50]))
);
// Pushing the colorPhotos to the db
const colorPhotosStreams = colorPhotoBuffers.map((buff) =>
Readable.from(buff)
);
const colorPhotoValues = await Promise.all(
colorPhotosStreams.map((stream, index) =>
pushToDbFromStream(stream, req, colorPhotos[index])
)
);
req.body.colors = JSON.parse(req.body.colors);
colorPhotoValues.forEach((value, index) => {
req.body.colors[index].colorPhoto = value.filename;
});
req.body.colors.forEach((color) => req.addedFiles.push(color.colorPhoto));
}
next();
});
exports.updateProduct = asyncHandler(async (req, _, next) => {
req.product = await Product.findByIdAndUpdate(req.params.id, req.body, {
runValidators: true,
new: true,
});
next();
});
exports.updateProduct = asyncHandler(async (req, _, next) => {
req.product = await Product.findByIdAndUpdate(req.params.id, req.body, {
runValidators: true,
new: true,
});
next();
});
```
There is a reference to the images in a color property of the product Schema. That uses the embedded document style. Instead, I could use the referenced way instead, and create new Color documents and update them individually.