I am trying to upload image to mongoDD from a react application and I have always gotten above error message which is crashing my application.
My Client code:
// to be triggered by onChange attribute of a file input
const uploadFileHandler = async (e) => {
const file = e.target.files[0];
const formData = new FormData();
formData.append("image", file);
try {
const config = {
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${userInfo.token}`,
},
};
if (file) {
setErrorMessage(""); // Clear any previous error message.
dispatch({ type: UPLOAD_CATEGORY_IMAGE_REQUEST });
const { data } = await axios.post("/api/uploads", formData, config);
if (data.image) {
const formatedData = {
public_id: `${Date.now()}`,
url: data,
};
console.log(formatedData);
} else {
dispatch({
type: UPLOAD_CATEGORY_IMAGE_FAIL,
payload: data.message,
});
}
} else {
// Handle the case where no file is selected.
setErrorMessage("Please select a file.");
}
} catch (error) {
console.error(error);
}
};
Extract from server.js:
app.use("/api/uploads", uploadRoutes);
uploadRoutes:
import path from "path";
import express from "express";
import { protect, adminCheck } from "../middleware/authMiddleware.js";
const router = express.Router();
import {
uploadFiles,
getListFiles,
getFile,
} from "../controllers/uploadController.js";
router.route("/").post(protect, adminCheck, uploadFiles).get(getListFiles);
router.route("/:filename").get(getFile);
export default router;
Extract from uploadController.js:
import asyncHandler from "express-async-handler";
import uploadFilesMiddleware from "../middleware/uploadMiddleware.js";
import { MongoClient, GridFSBucket } from "mongodb";
import getRequestUrl from "../utils/urls.js";
const mongoClient = new MongoClient(process.env.MONGO_URI);
const database = mongoClient.db(process.env.DATABASE);
const image = database.collection(process.env.IMAGE_BUCKET + ".files");
const bucket = new GridFSBucket(database, {
bucketName: process.env.IMAGE_BUCKET,
});
const uploadFiles = asyncHandler(async (req, res) => {
try {
await uploadFilesMiddleware(req, res);
if (req.file == undefined) {
return res.send({
message: "You must select a file.",
});
}
return res.send({
image: `${req.file.filename}`,
message: "File has been uploaded.",
});
} catch (error) {
console.log(error);
return res.send({
message: "Error when trying upload image: ${error}",
});
}
});
My uploadFilesMiddleware:
import dotenv from "dotenv";
import multer from "multer";
import { GridFsStorage } from "multer-gridfs-storage";
import util from "util";
dotenv.config();
const storage = new GridFsStorage({
url: process.env.MONGO_URI,
options: { useNewUrlParser: true, useUnifiedTopology: true },
file: (req, file) => {
try {
const match = ["image/png", "image/jpeg", "image/jpg"];
if (match.indexOf(file.mimetype) === -1) {
throw new Error("Invalid file format");
}
console.log("image-bucket: ", process.env.IMAGE_BUCKET);
console.log("upload-file: ", file);
return {
bucketName: process.env.IMAGE_BUCKET,
filename: `${Date.now()}-${process.env.BUSINESS}-${file.originalname}`,
};
} catch (error) {
console.log("error: ", error);
}
},
});
const uploadFiles = multer({ storage: storage }).single("image");
const uploadFilesMiddleware = util.promisify(uploadFiles);
export default uploadFilesMiddleware;
Dependencies and versions extracted from package.json:
"multer": "^1.4.5-lts.1", "multer-gridfs-storage": "^5.0.2",
Full error message:
C:\Users\streu\OneDrive\Documents\React\foodstore-mern\server\node_modules\multer-gridfs- storage\lib\gridfs.js:306
[0] id: f._id,
[0] ^
[0]
[0] TypeError: Cannot read properties of undefined (reading '_id')
[0] at GridFSBucketWriteStream.emitFile (C:\Users\streu\OneDrive\Documents\React\foodstore- mern\server\node_modules\multer-gridfs-storage\lib\gridfs.js:306:31)
[0] at GridFSBucketWriteStream.emit (node:events:525:35)
[0] at finish (node:internal/streams/writable:748:10)
[0] at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
[0]
[0] Node.js v18.16.1
[1] Proxy error: Could not proxy request /api/uploads from localhost:3000 to http://127.0.0.1:5000.
[1] See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNRESET).
[1]
[0] [nodemon] app crashed - waiting for file changes before starting...
Please I have spent two days debugging with no headways. Can someone assist here?
I have deleted node_modules and package-lock.js and ran npm install to no avail.
I have tried to dispatch e.target.files[0] to redux action and it did not work.
I checked and find out that all multer-gridfs-storage dependencies are up to date ad are listed in below upject:
{
'@types/express': '^4.17.6',
'@types/mongodb': '^3.5.25',
'@types/multer': '^1.4.3',
'@types/pump': '^1.1.0',
'has-own-prop': '^2.0.0',
'is-generator': '^1.0.3',
'is-promise': '^4.0.0',
'lodash.isplainobject': '>=0.8.0',
mongodb: '>=2',
'mongodb-uri': '^0.9.7',
pump: '^3.0.0'
}
I tried the same workflow on another application and it worked.
I was having the same issue. I resolved it by changing the mongodb version to 5.9.1