File Uploads #02

0_CyberLover_0·2022년 4월 27일
0

Node.JS #05

목록 보기
16/19

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}를 꺼내준다. 그리고 pathfindByIdAndUpdate에 보낸다.

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')

아바타를 변경하지 않았는데 에러가 났다. 콘솔을 확인해 보니 에러가 뜬다.

undefinedpath property를 읽을 수 없다고 한다.

무슨 말이냐면 fileundefined라서 path를 찾을 수 없다는 거다.

파일을 보내지 않으면 req안에 fileundefined가 된다.

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이 존재한다는건 userinput으로 file을 보냈다는 거다,

file이 존재하지 않는다면 사용자가 input을 건드리지 않았다는 거고,

file이 존재하지 않으면 기존 avatarUrl로 저장 할거다.

새로운 avatarUrlsessionuser 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

imgsrcloggedInUser.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가 생겼으니 img100pxwidth,height를 설정해 준다.

CSS 작업하기 전까지만 일단 이렇게 사용 하기로 한다.

새로고침을 하면 사진이 에러가 난다. 이미지가 보여야 되는데 검사를 해서 확인해 본다.

src는 괜찮은것 같다. 콘솔에서 확인하면 이미지를 찾을수 없다고 한다.

새로운 탭으로 열어서 확인해 보면

Cannot GET /users/uploads/597ad456bcec6a0743a383a1653d5499

링크에 문제가 있다. 이미지가 uploads/로 저장되어 있는데 여기서는 상대 URl로 바뀌었다.

block content
    img(src="/" + loggedInUser.avatarUrl, width="100",height="100")

이렇게 바꿔준다. 새로고침을 하고 확인해보면 아직도 에러가 나고 있긴 하다.

이유는 해당 URL을 만들지 않았다. Express한테 uploads폴더가 새로 생겼다고 말해준적이 없다.

링크에 있는 모든 것들이 router에 있어야 되는데 그렇지 않다.

profile
꿈꾸는 개발자

0개의 댓글