So far I managed to make an image to be uploaded on mongo, but I cant make it to get saved on disk.
React component
const handleUploadPhoto = evt => {
evt.preventDefault();
const uploads = photos.map(async photo => {
const formData = new FormData();
formData.append('photo', photo);
await axios.post(
`${baseUrl}/api/photo/upload/${JSON.parse(localStorage.getItem('loggedUser'))._id}`,
formData,
{ headers: {
'Content-Type': 'multipart/form-data'
}},
);
});
};
Upload route with multer setup:
const FILE_PATH = 'uploads';
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, FILE_PATH),
filename: (req, file, cb) => {
const newFileName = `${Math.floor(Math.random() * 1000000)}-${file.originalname.split('.')[0]}${path.extname(file.originalname)}`;
cb(null, newFileName);
},
});
const upload = multer({
storage,
fileFilter (req, file, cb) {
if (!file.originalname.match(/\.(jpeg\jpg\png)$/)) {
cb(new Error('Only upload jpg and png files.'));
}
cb(undefined, true);
}
});
router.post('/upload/:userid', upload.single('photo'), uploadPhoto);
And the controller:
const { name, data, mimetype } = req.files.photo;
User
.findById(req.params.userid)
.exec((error, user) => {
if (error || !user) return res.status(404).json({ message: error.message, });
const newPhoto = new Photo({
photo: {
mimetype,
data,
path: `${__dirname}/uploads/${name}`,
name,
},
owner: user._id,
});
newPhoto.save((error, photo) => {
if (error) return res.status(401).json({ message: error, });
user.photos.push(newPhoto._id);
user.save();
return res.status(201).json({
message: `Image created`,
path: photo.path,
});
});
});
So, as you can see, I am saving the data as Buffer in mongodb and I want to actually save the image on disk and only the name, mymetype and the path(location on disk) of the image on mongodb.
First: You are using upload.single()
to get the uploaded file
router.post('/upload/:userid', upload.single('photo'), uploadPhoto);
and upload.single()
is gonna attach the file to req.file
not req.files
. which, your getting the uploaded file using req.files
, which is used to upload multiple files:
const { name, data, mimetype } = req.files.photo;
Second: __dirname
get the path of the current file not the current working directory, for more info , so you should not use __dirname
, instead use ./
. So I am assuming your actually saving the file to a different directory but using the wrong path to save in Mongo.
Third: You are using multer.diskStorage
which automatically saves the file to disk, and because you are using diskStorage
you don't have access to the buffer
according to docs. read the docs cause apparently you are using the wrong properties of uploaded files in here:
const { name, data, mimetype } = req.files.photo;
You got to replace it with:
const { filename, mimetype } = req.file; // don't have access to buffer in diskStorage