I am trying to create upload profile image method that help user upload their profile picture on website but I am having trouble with I dont know how to send the image from client to server and make those image store on cloudinary or firebase.
My routes look like this: ProfileAPI.js
const express = require("express");
const router = express.Router();
const { body, param } = require("express-validator");
const { catchErrors } = require("../errors/errorHandlers");
const multer = require('multer');
const uuidv4 = require('uuid/v4');
const upload_dir = './images';
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, upload_dir);
},
filename: (req, file, cb) => {
cb(null, `${uuidv4()}-${file.filename.toLowerCase}`);
}
});
const upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if (
file.mimetype == 'image/png' ||
file.mimetype == 'image/jpg' ||
file.mimetype == 'image/jpeg'
) {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
}
}
});
const {
getUserProfile,
getUsersPublicProfile,
lookUpId,
updateUserProfile,
updateUserEmail,
deleteUserProfile,
// deleteUserSkill,
addPlayersProfile,
getCreatedPlayers,
updatePlayersProfile,
deleteUserCreatedPlayer,
} = require("./profilesController");
router.post(
"/upload",
upload.single('profileImg'),
updateUserProfile
);
So key points are the setup of storage which tells where to upload + the file filter in upload, right?
And the route.post which will `upload.single('profileImg'), right? the route will include my controller for updateUserProfile which can be found here: profilesController.js
exports.updateUserProfile = async (req, res) => {
const userId = req.session.passport.user.id;
// This array will contain all the update functions to run.
const updates = [];
// If a gravatar url has not been generated, do it now.
const pictureValue = gravatar.url(
req.body.email,
{ s: "100", r: "pg", d: "retro" },
true
);
const payload = {
fullname: req.body.fullname,
location: req.body.location,
webpage: req.body.webpage,
linkedin: req.body.linkedin,
institution: req.body.institution,
bio: req.body.bio,
major: req.body.major,
mergedTo: userId,
picture: pictureValue,
skillone: req.body.skillone,
skilltwo: req.body.skilltwo,
skillthree: req.body.skillthree
};
}
So now to the frontend code (react.js):
This is the form I am loading in my react app:
UserProfile.js
const UserProfile = (serverUserData) => {
const appState = useContext(GlobalContext);
const { currentUser } = appState;
const { email, picture, name } = currentUser;
const [isVerified, setIsVerified] = useState(false);
const checkVerificationData = () => {
axios.get("/api/v1/profiles/profile").then((res) => {
const { data } = res;
if (data.verifiedDT) {
setIsVerified(data.verifiedDT);
}
});
};
useEffect(() => {
checkVerificationData();
}, [isVerified]);
// Upload user avatar function
const [imageSelected, setImageSelected] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
const formData = new FormData();
formData.append('email', email);
formData.append('name', name);
formData.append('profileImg', imageSelected);
axios
.post(`/upload`, formData)
.then(() => console.log("success"))
.catch(err => console.log(err));
};
const onFileChange = (e) => {
setImageSelected({ profileImg: e.target.files[0] });
};
};
const classes = useStyles();
return (
<div className={classes.root}>
<Grid item xs={12}
container
direction="row"
justify="center"
alignItems="center"
spacing={4}>
<Grid item>
<Grid item>
<UserCard
picture={currentUser.picture}
userEmail={email}
name={name}
isVerified={isVerified}
handleSubmit={handleSubmit}
onFileChange={onFileChange}
/>
<br />
</Grid>
and here is where user can upload their profile photo: UserCard.js
{picture ? (
<div>
<Avatar
src={picture}
alt="Avatar"
className="avatar--profile_image"
/>
<input
type="file"
onChange={onFileChange}
/>
<button onClick={handleSubmit}>Submit</button>
</div>
) : (
<AccountCircleIcon className="avatar--profile_image" />
)}
So when entering things and hitting the Add Button my api states that req.file is undefined and I cannot find out why.
Can anyone help me drilling down the error?
contentType: "multipart/form-data"inaxiospost request first paramenter.body-parserto your express app. Other things seem okay to me