controller
를 마무리 해본다.
이제 req.file
이 생겼고, 경로를 얻어야 한다.
userController.js
에서
export const postEdit = async (req, res) => {
const {
session: {
user: { _id },
},
body: { name, email, username, location },
file: { path },
} = req;
req
에서 file:{ path}
를 꺼내준다. 그리고 path
를 findByIdAndUpdate
에 보낸다.
const updatedUser = await User.findByIdAndUpdate(
_id,
{
avatarUrl:path,
name,
email,
username,
location,
},
avatarUrl:path
를 입력해준다. 여기서 약간의 문제가 있다.
사용자가 아바타를 바꾸지 않았을때 발생한다.
그전에 콘솔로 확인해 본다.
export const postEdit = async (req, res) => {
const {
session: {
user: { _id },
},
body: { name, email, username, location },
file: { path },
} = req;
console.log(path);
사용자가 아바타를 바꾸지 않았을때 어떻게 되는지 확인하기 위해서다.
새로고침 한 다음 아바타는 변경하지 않고 이름만 변경해서 프로필을 업데이트 해보았다.
TypeError: Cannot read properties of undefined (reading 'path')
아바타를 변경하지 않았는데 에러가 났다. 콘솔을 확인해 보니 에러가 뜬다.
undefined
의 path property
를 읽을 수 없다고 한다.
무슨 말이냐면 file
이 undefined
라서 path
를 찾을 수 없다는 거다.
파일을 보내지 않으면 req
안에 file
은 undefined
가 된다.
export const postEdit = async (req, res) => {
const {
session: {
user: { _id },
},
body: { name, email, username, location },
file,
} = req;
console.log(file);
이렇게 해주고 다시 테스트해 본다. 이름만 변경하고 업데이트 해본다. 저장 되었고
콘솔을 확인해 보면 파일은 undefined
이다.
file
이 존재하지 않으면 avatarUrl:file.path
를 사용 할수 없다.
avatarUrl
을 빈 내용으로 만드는거랑 마찬가지이다.
사용자가 이미 아바타가 있다면 undefined
인 아바타를 보내면 안된다.
대신에 session
으로 user
정보를 사용 할수 있었다.
export const postEdit = async (req, res) => {
const {
session: {
user: { _id,avatarUrl },
},
body: { name, email, username, location },
file,
} = req;
console.log(file);
const updatedUser = await User.findByIdAndUpdate(
_id,
{
avatarUrl: file ? file.path : avatarUrl,
name,
email,
username,
location,
},
user
에는 avatarUrl
이 있다. 그래서 기존 avatarUrl
을 찾을수 있다.
그리고 간단한 if else
를 사용하면 된다.
파일이 존재한다면 그러니까 유저가 form
으로 파일을 보낸다면 file.path
을 쓰고
존재하지 않는다면 기존 avatarUrl
을 유지할거다.
어떤 때는 파일이 undefined
일 수 있다. file
이 존재한다면 file.path
가 있다는 말이다.
file
이 존재한다는건 user
가 input
으로 file
을 보냈다는 거다,
file
이 존재하지 않는다면 사용자가 input
을 건드리지 않았다는 거고,
file
이 존재하지 않으면 기존 avatarUrl
로 저장 할거다.
새로운 avatarUrl
을 session
의 user object
에 있는 기존 것으로 하겠다는 거다.
session
에는 user object
가 있고 거기에 있는 정보를 사용할 수 있다.
_id
를 사용한 것처럼 기존의 avatarUrl
을 사용 할수 있다.
테스트를 해본다. 먼저 아바타를 설정하고 업데이트 프로필 버튼을 클릭해준다.
업데이트가 잘 된것같다. DB
에서도 확인해 본다.
db.users.find({})
해주면 여러 정보가 나오는데 avatarUrl
에도 나오는데
uploads/
와 랜던된 값이 같이 나온다.
이제 uploads
폴더를 보면 새로운 파일이 생겨 있다.
commit
하기전에uploads
폴더를.gitignore
에 추가하는거를 잊지 말자
/node_modules
.env
/uploads
gitignore
에 추가하면 깃허브에 폴더가 업로드 되지 않는다.
form
에 파일을 보낼때도 있고 아닐때도 있다.
그래서 form
으로 파일을 보내는걸 확인하면 그 파일을 새로운 avatarUrl
로 저장해주는 거다.
파일을 보내지 않으면 user
에 기존 avatarUrl
이 그대로 새로운 avatarUrl
로 된다.
그리고 이제 다시 프로필을 업데이트 해본다. 이번에는 아바타 파일을 보내지 않을거다.
다시 DB
를 확인해 보면 avatarUrl
에는 그대로 유지 되고 있다.
이제 파일을 보내지 않아도 에러가 생기지 않는다.
이렇게 파일을 업로드하고, 파일URL
을 저장하게 되었다.
절대로
DB
에 파일을 저장하면 안된다.
대신에 폴더에 파일을 저장하고 DB
에는 그 파일의 위치만 저장하는거다.
이제 user
에는 avatarUrl
이 있으니 사용해 볼수 있다.
그래서 edit-profile
페이지에다가 이미지를 만들거다.
block content
img(src=loggedInUser.avatarUrl, width="100",height="100
img
의 src
는 loggedInUser.avatarUrl
이다.
user
에는avatarUrl
이 있다는걸 명심한다.
middleware.js
에서
export const localsMiddleware = (req, res, next) => {
res.locals.loggedIn = Boolean(req.session.loggedIn);
res.locals.siteName = "Wetube";
res.locals.loggedInUser = req.session.user || {};
next();
};
다시 한번 설명하면 loggedInUser
는 현재 로그인 된 사용자고 localsMiddleware
를 통해 pug
에 전달되고 있다.
locals
에 저장하는 모든 정보는 views
에서 사용 가능하다.
img
가 생겼으니 img
에 100px
의 width
,height
를 설정해 준다.
CSS
작업하기 전까지만 일단 이렇게 사용 하기로 한다.
새로고침을 하면 사진이 에러가 난다. 이미지가 보여야 되는데 검사를 해서 확인해 본다.
src
는 괜찮은것 같다. 콘솔에서 확인하면 이미지를 찾을수 없다고 한다.
새로운 탭으로 열어서 확인해 보면
Cannot GET /users/uploads/597ad456bcec6a0743a383a1653d5499
링크에 문제가 있다. 이미지가 uploads/
로 저장되어 있는데 여기서는 상대 URl
로 바뀌었다.
block content
img(src="/" + loggedInUser.avatarUrl, width="100",height="100")
이렇게 바꿔준다. 새로고침을 하고 확인해보면 아직도 에러가 나고 있긴 하다.
이유는 해당 URL
을 만들지 않았다. Express
한테 uploads
폴더가 새로 생겼다고 말해준적이 없다.
링크에 있는 모든 것들이 router
에 있어야 되는데 그렇지 않다.