edit profile / change password
íėž ė ëĄë - multer / req.file / express.static()
git restore --staged ėëŽ íīęē°
ėŽíęđė§ ë°°ėī ęē ëģĩėĩ
githubėë§ ėŽëĶž
ėëŽ ëīėĐ
ëĄę·ļėļ íė§ ėė userę° ė§ė ėĢžė ė°―ė localhost:4000/users/editëĨž ė ë Ĩíī ëĪėīėĪë Īęģ í ë íëĐīėë 'undefinedė name ėėąė ė―ė ė ėëĪ'ë ėëŽę° ëŽëĪ.
ėëŽ ėėļ
ëĄę·ļėļė íė§ ėėžëĐī req.session.userę° undefined ėíëžė res.locals.loggedInUserë undefinedę° ëëĪ.
ë°ëžė, edit-profile.pug íėžėė undefined(loggedInUser)ė name ėėąė ė―ė ė ėëĪëĐ° ėëŽę° ëĻęē ëë ęēėīëĪ.
ėëŽ íīęē°
ëĄę·ļėļ íė§ ėė userë edit-profile íėīė§ė ė ę·ží ė ėëëĄ localsMiddlewareëĨž ėė íëĪ.
userę° ëĄę·ļėļ íė§ ėė req.session.userę° undefinedėļ ęē―ė°ėë res.locals.loggedInUserę° {}(undefined ėë)ė ę°ė ę°ė§ëëĄ íĻėžëĄėĻ ëĄę·ļėļ íė§ ėė userëĨž íŽíĻíī ëęĩŽë ė§ edit-profile íėīė§ëĨž ëģž ė ėëëĄ íëĪ.
// middlewares.js
export const localsMiddleware = (req, res) => {
res.locals.siteName = "Wetube";
res.locals.loggedIn = Boolean(req.session.loggedIn);
res.locals.loggedInUser = req.session.user || {}; // ėė â
next();
};
âŧ req.session.loggedIn ëė ė res.locals.loggedInė ėŽėĐí ėë ėëĪ. (req / res ėĢžė!)
ëĄę·ļėļ íė§ ėė userë homeėė edit profile ëĐëīëĨž ëģž ė ėėžëŊëĄ ëĐëīëĨž íīëĶíī edit profile íėīė§ė ëĪėīėŽ ėë ėëĪ.
ę·ļëŽë, ëĄę·ļėļ íė§ ėė userë ė§ė ėĢžė ė°―ė localhost:4000/users/editė ė
ë Ĩíī ëĪėīėĪë Īęģ í ė ėëĪ.
ėėė ėīë° ęē―ė°ėë (userę° ëĄę·ļėļ íė§ ėė ęē―ė°ėë) loggedInUserė ę°ėī undefinedę° ëė§ ėëëĄ ėĪė íëĪ.
ëĪë§, ėĪė ëĄ ëĄę·ļėļ íė§ ėė userë edit profile íėīė§ė ëĪėīėėë ėëęļ° ëëŽļė íīëđ íėīė§ëĄ ė ę·ž ė login íėīė§ëĄ redirect ėėžėž íëĪ.
ėīëĨž ėíī protectorMiddlewareëĨž ë§ëĪėīėž íëĪ.
// middlewares.js
export const protectorMiddleware = (req, res, next) => {
if (req.session.loggedIn) {
next();
} else {
return res.redirect("/");
}
};
edit profile íėīė§ëŋ ėëëž logout, upload video, edit video, delete video íėīė§ėė ëí, controllerę° ėĪíëęļ° ė ė protectorMiddlewareę° ėĪíëëëĄ íėŽ, íėīė§ė ė ę·žė ėëíë userę° ëĄę·ļėļë userėļė§ ėëė§ė ë°ëž ę°ę° ëĪëĨļ íėīė§ëĨž ëģīėŽėĢžëëĄ íīėž íëĪ.
// userRouter.js
import { protectorMiddleware } from "../middlewares";
userRouter.get("logout", protectorMiddleware, logout);
userRouter.route("/edit").all(protectorMiddleware).get(getEdit).post(postEdit);
// videoRouter.js
import { protectorMiddleware } from "../middlewares";
videoRouter.route("/:id([0-9a-f]{24})/edit").all(protectorMiddleware).get(getEdit).post(postEdit);
videoRouter.route("/upload").all(protectorMiddleware).get(getUpload).post(postUpload);
videoRouter.route("/:id([0-9a-f]{24})/delete").all(protectorMiddleware).get(deleteVideo);
âŧ upload video ëĐëīë ëĄę·ļėļ í userë§ ëģž ė ėëëĄ base.pug íėžė ėė íëĪ.
ííļ, ë°ëëĄ ëĄę·ļėļ ëėī ėė§ ėė userë§ ė ę·ží ė ėë íėīė§ë ėëĪ.
ėīëĨž ėíī publicOnlyMiddlewareëĨž ë§ëĪėīėž íëĪ.
// middlewares.js
export const publicOnlyMiddleware = (req, res, next) => {
if (!req.session.loggedIn) {
next();
} else {
return res.redirect("/");
}
};
github ëĄę·ļėļęģž ęīë Ļë route(github/start, github/finish)ė join, login íėīė§ėë ëĄę·ļėļ íė§ ėė userë§ ė ę·ží ė ėëëĄ íīėž íëĪ.
// userRouter.js
import { publicOnlyMiddleware } from "../middlewares";
userRouter.get("/github/start", publicOnlyMiddleware, startGithubLogin);
userRouter.get("/github/finish", publicOnlyMiddleware, finishGithubLogin);
// rootRouter.js
import { publicOnlyMiddleware } from "../middlewares";
rootRouter.route("/join").all(publicOnlyMiddleware).get(getJoin).post(postJoin);
rootRouter.route("/login").all(publicOnlyMiddleware).get(getLogin).post(postLogin);
ëĻžė req.session.useręģž req.bodyėė user ė ëģīëĨž ę°ė ļėėž íëĪ.
ėīë ES6 ę°ėēī ëŽļëēė ėŽėĐíī ëģīëĪ ę°ęē°íęē ííí ė ėëĪ.
const id = req.session.user._id;
const { name, email, username, location } = req.body;
ėė ėëė ė―ëë ëėžíëĪ.
const {
session: {
user: { _id },
},
body: { name, email, username, location },
} = req;
ðĄ model.findByIdAndUpdate()
íėŽ ëĄę·ļėļ ëėī ėë user objectė _id ėėą ę°ęģž userę° formė ė ë Ĩí profile ėė ėŽíëĪė ë°ėėė ėīëĨž model.findByIdAndUpdate()ëĨž ėīėĐíī ë°ėīí°ëē ėīėĪëĨž ė ë°ėīíļ í ė ėëĪ.
export const postEdit = async (req, res) => {
const {
session: {
user: { _id },
},
body: { name, email, username, location },
} = req;
await User.findByIdAndUpdate(_id, {
name,
email,
username,
location,
});
return res.render("edit-profile", { pageTitle: "Edit Profile" });
};
ðĄ ëŽļė ë°ė
ę·ļë°ë° ėīë ęē ėėąíëĐī DBë ė ë°ėīíļę° ëė§ë§, res.renderė ėíī ëĪė ëėę° edit-profile íėīė§ėë ėŽė í ėė ė value ę°ëĪėī ė ë Ĩëėī ėëĪ.
ę·ļ ėīė ë DBėė user objectë ė ë°ėīíļę° ëėė§ë§, sessionė ė ë°ėīíļ ëė§ ėėęļ° ëëŽļėīëĪ.
ėėļí ėĪëŠ
íëĐī, edit-profile íėīė§ė formė value ę°ëĪė loggedInUserė ėėą ę°ëĪėīëĪ.
ę·ļë°ë° req.session.userė ę°ėī localsMiddlewareė ėíī ęģ§ res.locals.loggedInUserė ę°ėī ëëĪ.
req.session.userë ëĄę·ļėļ í ë postLogin ėŧĻíļëĄĪëŽėė ë§ëĪėīė§ ęēėžëĄėĻ user objectė ę°ė ę°ė§ëĪ.
ę·ļëŽëŊëĄ ëŽļė ëĨž íīęē°íęļ° ėíīėë req.session.userė ėė ë user objectëĨž ëĪė í ëđíīėž íëĪ.
DBė ė
ë°ėīíļí ëīėĐė sessionėë ė
ë°ėīíļ íĻėžëĄėĻ íëĄ íļėëėë ë°ėëëëĄ íīėž íëĪ.
ðĄ ė§ė session ė ë°ėīíļ
export const postEdit = async (req ,res) => {
const {
session: {
user: { _id },
},
body: { name, email, username, location },
} = req;
// DB ė
ë°ėīíļ
await User.findByIdAndUpdate(_id, {
name,
email,
username,
location,
});
// session ė
ë°ėīíļ
req.session.user = {
...req.session.user, // ęļ°ėĄīė ę°ëĪė ė ëŽí í ėė ėŽíëĪë§ ëŪėīė°ęļ°
name,
email,
username,
location,
};
// renderëĨž redirectëĄ ėė íĻ
return res.redirect("/users/edit");
};
ë§ė§ë§ė res.render("edit-profile")ė redirect("/user/edit")ėžëĄ ėė íīėž íëĪ.
sessionė ė
ë°ėīíļí í localsMiddelwareëĨž ëĪė ëķëŽėėž íęļ° ëëŽļėīëĪ.
localsMiddlewareëĨž íĩíī ė
ë°ėīíļí user ė ëģīëĨž res.locals.loggedInUserė í ëđí ė ėëĪ.
locasMiddlewareë routeëĨž ė°ūęļ° ė ė ėĪíëëŊëĄ ëĻėí pug íėžė ë ëë§ í ęē ėëëž redirect íīėž íëĪ.
ðĄ updatedUser ėėą
ęļ°ëģļė ėžëĄ model.findByIdAndUpdate()ė update ëęļ° ė ė ë°ėīí°ëĨž return íëĪ.
update ë íė ë°ėīí°ëĨž return íëëĄ íë ĪëĐī new: true
ėĪė ė ėķę°íīėž íëĪ.
âŧ User.findByIdAndUpdate()ė 3ę°ė ėļėëĨž ėĢžęģ ėëĪ.
export const postEdit = async (req ,res) => {
const {
session: {
user: { _id },
},
body: { name, email, username, location },
} = req;
// DB ė
ë°ėīíļ
const updatedUser = await User.findByIdAndUpdate(
_id,
{
name,
email,
username,
location,
},
{ new: true }, // ėķę° â
);
// session ė
ë°ėīíļ
req.session.user = updatedUser;
// localsMiddlewareę° ėĪíëëëĄ redirect
return res.redirect("/users/edit");
};
ėëí ëëĄ ė ėëíëĪ.
ę·ļëŽë í ę°ė§ ęģ ë Īíīėž í ėŽíėī ëĻė ėëĪ.
ėė ë usernameęģž emailėī ėīëŊļ ëęĩ°ę° ėŽėĐ ėĪėīëžëĐī ę·ļ ę°ëĪëĄ ė
ë°ėīíļ ëėīėë ėëëĪ.
ė―ë ėąëĶ°ė§
ðĄ ėĪëĩ
ėžëĻė joinėė ėŽėĐíë ë°Đëēė ėĻëģīėëĪ.
export const postEdit = async (req, res) => {
const {
session: {
user: { _id },
},
body: { name, email, username, location },
} = req;
// username, email ėĪëģĩ ęēėŽ (ėķę° â)
const exists = await User.exists({ $or: [{ username }, { email }] });
if (exists) {
return res.render("edit-profile", {
pageTitle: "Edit Profile",
errorMessage: "This username/email is already taken.",
});
}
// DB ė
ë°ėīíļ
const updatedUser = await User.findByIdAndUpdate(
_id,
{
name,
email,
username,
location,
},
{ new: true }
);
// session ė
ë°ėīíļ
req.session.user = updatedUser;
// localsMiddlewareę° ėĪíëëëĄ redirect
return res.redirect("/users/edit");
};
ę·ļëŽë ėīë ęē ėėąíëĐī, nameėīë locationë§ė ëģęē―íęģ usernameėīë emailė ëģęē―íė§ ėė ęē―ė°ėë ėëŽ ëĐėė§ę° ëĻęē ëėī, nameėīë locationë§ė ëģęē―í ėę° ėëĪ.
ðĄ íīëĩ
ė ë°Đëē ëė ė usernameęģž emailė ėė ėŽëķëĨž ëĻžė íėļí í, ėė ëėëĪëĐī ë°ėīí°ëē ėīėĪė ę·ļ ėė ë ę°ęģž ëėží ę°ėī ėĄīėŽíëė§ íėļíë ë°Đëēė ėŽėĐíë Īęģ íëĪ.
export const postEdit = async (req ,res) => {
// req.session.useręģž req.bodyėė user ė ëģīëĨž ę°ė ļėī
const {
session: {
user: { _id },
},
body: { name, email, username, location },
} = req;
// username, email ėĪëģĩ ęēėŽ
if (username !== req.session.user.username) { // formėė usernameėī ėė ëėëĪëĐī
const exists = await User.exists({ username }); // DBė ėė ë ę°ęģž ëėží ę°ėī ėëė§ íėļ
if (exists) { // ėĪëģĩë ę°ėī ėëĪëĐī ėëŽ ëĐėė§ ëģīėŽėĢžęļ°
return res.render("edit-profile", { pageTitle: "Edit Profile", errorMessage: "This username is already taken."});
}
}
if (email !=== req.session.user.email) { // formėė ėė ëėëĪëĐī
const exists = await User.exists({ username }); // DBė ėė ë ę°ęģž ëėží ę°ėī ėëė§ íėļ
if (exists) { // ėĪëģĩë ę°ėī ėëĪëĐī ėëŽ ëĐėė§ ëģīėŽėĢžęļ°
return res.render("edit-profile", { pageTitle: "Edit Profile", errorMessage: "This email is already taken."});
}
}
// ėė ë username íđė emailėī DBė ėë ę°ęģž ėĪëģĩëė§ ėėėī íėļëëĐī
// DB ė
ë°ėīíļ
const updatedUser = await User.findByIdAndUpdate(
_id,
{
name,
email,
username,
location,
},
{ new: true },
);
// session ė
ë°ėīíļ
req.session.user = updatedUser;
// localsMiddlewareę° ėĪíëëëĄ redirect
return res.redirect("/users/edit");
};
postEdit ėŧĻíļëĄĪëŽė íĻęŧ ėėąíė§ ėęģ password ëģęē―ė ėí ėŧĻíļëĄĪëŽëĨž ë°ëĄ ë§ë ėīė ë
ëĪëĨļ user ė ëģīë ëĄę·ļėļ íė§ ėė ëŠĻë userëĪėī ëģęē―í ė ėë ë°ëĐī,
passwordë githubëĨž íĩíī ëĄę·ļėļ í userëĪęđė§ë ëģęē―í ė ėęļ°
ëëŽļėīëĪ.
ëí, password ëģęē― ė User.findByIdAndUpdate() ë§ęģ user.save()ëĨž ėŽėĐíęģ ė íëĪ.
ėīëŽí ė°Ļėīė ëĪ ëëŽļė password ëģęē―ė ėí íėīė§ëĨž ë°ëĄ ë§ëĪėëĪ.
ėŽíęđė§ í ęē ëģĩėĩ
githubėë§ ėŽëĶž
githubëĨž íĩíī ëĄę·ļėļ í userë change password íėīė§ė ė ę·ží ė ėėīėž íëĪ.
githubëĄ ëĄę·ļėļ í userë 'Change Passowrd â'ëĨž ëģž ė ėëëĄ edit-profile.pug íėžė ėė íëĪ.
âŧ passwordëĄ ëĄę·ļėļí ėŽëë§ ė ę·žíīėž íë ėŧĻíļëĄĪëŽę° ë§ėė§ëĪëĐī, ėīëĨž ėėė ë§ëĪėë protectorMiddlewareėēëž middlewareëĨž ë§ëĪėī ėēëĶŽí ėë ėëĪ.
// change-password.pug
if !loggedInUser.socialOnly
hr
a(href="change-password") Change Password →
âŧ ėë ęē―ëĄëĨž ėŽėĐíīëīĪëĪ. ėīë ė ë ęē―ëĄėļ a(href="/users/change-password")ė ę°ëĪ.
ëĻžė , íėŽ ëđë°ëēíļ(oldPassword)ę° ėžėđíëė§ íėļí í ėëĄėī ëđë°ëēíļ(newPassword)ė ėëĄėī ëđë°ëēíļ íėļ(newPassword2)ėī ėžėđíëė§ íėļíëĪ.
ëŠĻë ęē ëŽļė ėëĪëĐī ëđë°ëēíļëĨž ëģęē―í í DBė ė ėĨíīėž íëĪ.
ëđë°ëēíļëĨž DBė ė ėĨí ëë password hashingė ėíī pre save middlewareëĨž ęą°ėģėž íëĪ.
ę·ļë°ë° pre save middlewareë 'User.create()' íđė 'user.save()'ëĨž íĩíīėë§ ėĪí ę°ëĨíëĪ. (User.findByIdAndUpdate() ėŽėĐ ėėë pre hookėī ėëëė§ ėëëĪ.)
ėī ęē―ė°ėë user.save()
ëĨž ėŽėĐíęļ° ėíī ëĻžė userëĨž ė°ūėėž íëĪ.
export const postChangePassword = async (req, res) => {
// req.session.useręģž req.bodyėė user ė ëģīëĨž ę°ė ļėī
const {
session: {
user: { _id, password },
},
body: { oldPassword, newPassword, newPassword2 },
} = req;
// old password ėžėđ ėŽëķ
const ok = await bcrypt.compare(oldPassword, password);
if (!ok) {
return res.status(400).render("change-password", {
pageTitle: "Change Password",
errorMessage: "The current password is incorrect.",
});
}
// new password íėļ ėžėđ ėŽëķ
if (newPassword !== newPassword2) {
return res.status(400).render("change-password", {
pageTitle: "Change Password",
errorMessage: "Password confirmation does not match.",
});
}
// password ëģęē― - DB ė
ë°ėīíļ â
const user = await User.findById(_id);
user.password = newPassword;
await user.save();
// session ė
ë°ėīíļ â
req.session.user.password = user.password;
// ëĄę·ļėėėíī
return res.redirect("/users/logout");
};
postChangePassword ėŧĻíļëĄĪëŽėėë postEdit ėŧĻíļëĄĪëŽėėė ë§ė°Žę°ė§ëĄ ë§ė§ë§ė sessionė ė ë°ėīíļ íīėž íëĪ.
ėēė passwordëĨž ëģęē―í ëë ëŽļė ę° ėė§ë§, 2ëēė§ļëĄ passwordëĨž ëģęē―í ëëķí°ë ėīė ė passwordëĨž ëģęē―í ë sessionė ė ë°ėīíļ íīėĢžė§ ėėëĪëĐī ëŽļė ę° ë°ėíëĪ.
postChangePassword ėŧĻíļëĄĪëŽė ė ëķëķėė ęļ°ėĄīė passwordëĨž req.session.user.passwordė ëđęĩ
íęģ ėęļ° ëëŽļė ë°ë passwordëĨž sessionė ė
ë°ėīíļ íīėĢžė§ ėėžëĐī await bcrypt.compare(oldPassword, password)ė ę°ė falseę° ëë ęēėīëĪ.
ë°ëžė, ëĪëĨļ user ė ëģīëĨž ëģęē―í ëė ë§ė°Žę°ė§ëĄ passwordëĨž ëģęē―í ëë dbëĨž ė
ë°ėīíļ í íė sessionë ę°ėī ęž ė
ë°ėīíļ
íīėĪėž íëĪ.
+íđė ėëė ę°ėī ėėąíëĪëĐī sessionė ė
ë°ėīíļ íīėĢžė§ ėėë ëëĪ.
ėēėëķí° DBėė userëĨž ëķëŽė passwordëĨž ëđęĩí ëë sessionėī ėëëž DBėė ëķëŽėĪë ęēėīëĪ.
export const postChangePassword = async (req, res) => {
// req.session.useręģž req.bodyėė user ė ëģīëĨž ę°ė ļėī
const {
session: {
user: { _id }, // ėė â
},
body: { oldPassword, newPassword, newPassword2 },
} = req;
// old password ėžėđ ėŽëķ
const user = await User.findById(_id); // ėėđ ėė â
const ok = await bcrypt.compare(oldPassword, user.password); // ėė â
if (!ok) {
return res.status(400).render("change-password", {
pageTitle: "Change Password",
errorMessage: "The current password is incorrect.",
});
}
// new password íėļ ėžėđ ėŽëķ
if (newPassword !== newPassword2) {
return res.status(400).render("change-password", {
pageTitle: "Change Password",
errorMessage: "Password confirmation does not match.",
});
}
// password ëģęē― - DB ė
ë°ėīíļ
user.password = newPassword;
await user.save();
// ëĄę·ļėėėíī
return res.redirect("/users/logout");
};
githubëĄ ëĄę·ļėļíė§ ėęģ passwordëĨž ė
ë Ĩíī ęģė ė ë§ë userë avatarëĨž ė
ëĄëí ė ėęģ
passwordëĨž ė
ë Ĩíī ęģė ė ë§ëĪė§ ėęģ githubëĄ ëĄę·ļėļí userë avatarëĨž ėė í ė ėëëĄ í ęēėīëĪ.
ėīëŧęē ë°ąėëė íėžė ëģīëž ė ėëę°
edit-profile.pug íėžė labelęģž input(type="file") íę·ļëĨž ėķę°íëĪ.
//- edit-profile.pug
extends base
if errorMessage
span=errorMessage
form(method="POST")
label(for="avatar") avatar
input(name="avatar", type="file", accept="image/*", id="avatar")
//- ėīí ėëĩ
multerë íėžė ëĪėīëĄë í ė ėëëĄ ëėėĢžë middlewareëĨž ë§íëĪ.
Multer ė°ļęģ
npmė ėīėĐíī multerëĨž ėĪėđíëĪ.
$ npm i multer
multerëĨž ėīėĐíī íėžė ė
ëĄë íęļ° ėíīėë(íėžė ë°ąėëëĄ ëģīëīęļ° ėíīėë) formė multipart formėžëĄ ë§ëĪėīėž íëĪ.
form íę·ļė enctype="multipart/form-data"
ėėąė ėķę°íëĪ.
//- edit-profile.pug
form(method="POST", enctype="multipart/form-data")
label(for="avatar") avatar
input(name="avatar", type="file", accept="image/*", id="avatar")
//- ėīí ėëĩ
middlewares.js íėžė userę° ëģīëļ íėžė ėëēė uploads íīëė ė ėĨíë multer middlewareëĨž ë§ëĪėëĪ.
multer middlewareėë ėĩė
ëĪė ëīė ę°ėēīëĨž ëĢė ė ėëĪ.
destë destinationėžëĄė íėžėī ė ėĨë ėėđëĨž ë§íëĪ.
ė§ęļė ėëēė uploads íīë ėĶ, íë ëëžėīëļė ė ėĨíė§ë§ ëėĪė ë°ęŋ ęēėīëĪ.
íëĄė íļ íīëė uploads íīëëĨž ėėąí í .gitignore íėžė ėķę°íëĪ.
// middlewares.js
export const uploadFiles = multer({ dest: "uploads/" });
uploadFiles middlewareë avatar ėŽė§ė upload í ë ėŽėĐëëŊëĄ postEdit ėŧĻíļëĄĪëŽ ėėė ėŽėĐëėīėž íëĪ.
userRouter.js íėžė ėė íëĪ.
// userRouter.js
userRouter.route(/edit) // url
.all(protectorMiddleware)
.get(getEdit)
.post(uploadFiles.single("avatar"), postEdit);
// (multer middleware.multer ëĐėë("formėė ë°ėėŽ íėžė name"), controller)
multer middlewareë userę° íīëđ urlëĄ íėžė ëģīëīëĐī inputėė íėžė ë°ėė uploads íīëė ė ėĨí í ę·ļ íėž ė ëģīëĨž postEdit controllerė ė ëŽíëĪ.
ėīëŊļė§ íėžė ė
ëĄë íëĐī uploadFiles.single("avatar")ę° ėĪíëëĐīė ëĪėęģž ę°ė req.fileėī ë§ëĪėīė§ëĪ.
ėī ėĪ avatarUrlė ėíī íėí ęēė pathėīëĪ.
{
fieldname: 'avatar',
originalname: 'dd.gif',
encoding: '7bit',
mimetype: 'image/gif',
destination: 'uploads/',
filename: '2987fe268e63abe892b0a1c5932f6ee9',
path: 'uploads/2987fe268e63abe892b0a1c5932f6ee9',
size: 5075180
}
ėīëĨž ë°íėžëĄ postEdit ėŧĻíļëĄĪëŽëĨž ėė í ë ęģ ë Īíīėž í ėŽíėī ë ę°ė§ ėëĪ.
ë§ė― userę° profileė ėė í ë avatar íėžė ė ëĄëíė§ ėëëĪëĐī, file ëģėė ę°ėī undefinedę° ëėī pathëĨž ė°ūė ė ėėī ėëŽę° ë°ėíëŊëĄ pathëĨž ëģėëĄ ë§ëĪė§ ë§ęģ fileė ëģėëĄ ë§ëĪėīėž íëĪ.
ęļ°ėĄīė avatarę° ėë userę° profileė ėė í ë avatar íėžė ė ëĄëíė§ ėėėīë ėë ėë avatarę° ėŽëžė ļėë ėëëĪ. (ėėëë° ėë ęąļëĄ ëŪėīė°ęļ° ëëĐī ėëëĪ.)
// userController.js
export const postEdit = (req, res) => {
const {
session: {
user: { _id, avatarUrl }, // avatarUrlė ėķę°ëĄ ę°ė ļėĻëĪ.
},
body: { name, email, username, location },
file, // file: { path } ëžęģ ė°ëĐī 1ëē ėëŽę° ë°ėíëĪ.
} = req;
// ėĪëĩ
await User.findByIdAndUpdate(
_id,
{
avatarUrl: file ? file.path : avatarUrl,
// ę·ļëĨ file.pathëžęģ ė°ëĐī 2ëē ėëŽę° ë°ėíëĪ.
name,
email,
username,
location,
},
{ new: true }
);
};
ðĄ ėĪėí ęēė ë°ėīí°ëē ėīėĪėë íėžė ė ėĨíė§ ėëëĪë ęēėīëĪ!
ë°ėīí°ëē ėīėĪėë íėžė ėėđë§ ė ėĨíëĪ.
// edit-profile.pug
extends base
block content
if errorMessage
span=errorMessage
img(src="/" + loggedInUser.avatarUrl, width="100", heigh="100")
form(method="POST", enctype="multipart/form-data")
label(for="avatar") avatar
input(name="avatar", type="file", accept="image/*", id="avatar")
//- ėīí ėëĩ
ðĄ ė ë ęē―ëĄ ėŽėĐíęļ°
edit profile íėīė§ė img íę·ļëĨž ėķę°íëĪ.
src ėėąė ę°ė, "/"ëĨž ė°ė§ ėėžëĐī ėëėžëĄ ėë ęē―ëĄ(/users/uploads/ëļëžëļëž)ëĄ ëģíëëŊëĄ ėė "/"ëĨž ëķėŽėĪėž íëĪ.
ė ė―ëė ęē°ęģž src ę°ė /uploads/ds3jdksfj3kdflsfla2222kl ė ę°ė ę°ė ę°ė§ęē ëëĪ.
ðĄ express.static("ëļëžė°ė ė ë ļėķėíŽ íīë ėīëĶ")
ę·ļëŽë, ėė ę°ėī ėėąíīë íëĐīėë avatar ėīëŊļė§ę° ëĻė§ ėëëĪ.
ėīë expressę° uploadsëžë ęē―ëĄę° ėķę°ëėėė ëŠĻëĨīęģ , ëļëžė°ė ę° uploads íīëė ėë íėžė ëģž ė ėęļ° ëëŽļėīëĪ.
ëŽļė ëĨž íīęē°íęļ° ėíīėë sever.jsėė íėžėė /uploads ęē―ëĄëĨž ėķę°íęģ , ëļëžė°ė ę° ėīëĪ íīëëĨž ëģž ė ėėė§ ėĪė íīėž íëĪ. (static files serving)
express.static()ė ėīėĐíī íīë ëīė ëŠĻë íėžė ëļëžė°ė ė ë
ļėķ
ėíŽ ė ėëĪ.
// server.js
app.use("/uploads", express.static("uploads"));
ëęĩ°ę° /uploadsëĄ ę°ë Īęģ íëĐī, uploads íīëė ëŠĻë ëīėĐė ëģīėŽėĢžëëĄ íëĪ.
ėīė edit profile íėīė§ė avatar ėŽė§ėī ëĻë ęēė íėļí ė ėëĪ.
ė§ęļė íėžė ėëēė uploads íīëė ė ėĨíęģ ėëĪ.
ę·ļëŽë, íėžė ėëēė ė ėĨíīėë ėëëĪ.
ėīė ėëēëĨž ėĒ
ëĢíęģ ėëĄėī ėëēëĨž ë§ëĪęą°ë ėëēę° ėĢ―ėīëēëĶŽëĐī, ėëēė ė ėĨëėī ėë íėžëĪė ė ëķ ėęē ëęļ° ëëŽļėīëĪ.
ë°ëžė, íėžė ėė íęē ė ėĨíęļ° ėíīėë íėžė ėëēę° ėë ëĪëĨļ ęģģė ė ėĨíīėž íëĪ.
ėīë ėĪė ėëēė ėąė ë°°íŽí ë ė§ííīëģž ęēėīëĪ.
ííļ, userę° ė
ëĄëëĨž íĩíī avatar ėŽė§ė ë°ęŋ ëë§ëĪ ė
ëĄë í ëŠĻë íėžëĪėī uploads íīëė ė ėĨëęģ ėëĪ.
ėī ëí ëĪėė íīęē°íīëģž ęēėīëĪ.
ðĄ ėĪė íėžė Amazonė íë ëëžėīëļ ëąė ė ėĨíęģ , ë°ėīí°ëē ėīėĪėë íėžė urlė ė ėĨíīėž íëĪ!
git addëĨž ėëŠŧ íīė ëĪė unstaged areaëĄ ëīëĶŽęļ° ėíī git restore --staged [íėž ėīëĶ]
ė ė
ë Ĩíëë° ėëė ę°ė ėëŽę° ëīëĪ.
error: pathspec 'íėž ėīëĶ' did not match any file(s) known to git
í°ëŊļëėė íīëđ íėžėī ėë íīëëĄ ę°ė git fetch
ëĨž ė
ë ĨíëĪ.
(ėĢžė! íëĄė íļ íīëę° ėëëž 'íīëđ íėžėī ėë íīë'ėīëĪ.)