upload files

404·2022년 1월 26일
0

서버에 파일 업로드하기.

1. file input 만들기

// editProfile.pug
extends base.pug

block content
    if errMessage 
        div #{errMessage}
    img(src="/" + loggedInUser.avatarUrl, width="200", height="200")
    form(method="POST", enctype="multipart/form-data")
        label(for="avatar") Avatar
        input(type="file", id="avatar", name="avatar", accept="image/*")
        input(placeholder="Name", name="name", type="text", required, value=loggedInUser.name)
        input(placeholder="Email", name="email", type="email", required, value=loggedInUser.email)
        input(placeholder="Username", name="username", type="text", required, value=loggedInUser.username)
        input(placeholder="Location", name="location", type="text", required, value=loggedInUser.location)
        input(type="submit", value="Update Profile")

form 안에 labelinput을 만들어주고 img 파일만 업로드 할수 있도록 했다.
form 의 인코딩 타입을 "multipart/form-data" 으로 설정했는데 이것은 multer 미들웨어를 사용하기 위함이다. (multer의 설정값)

2. multer middleware

npm i multer

// middleware.js

import multer from "multer";

export const uploadFiles = multer({ dest: "uploads/" });

middleware.js 파일에 multer를 import하고 uploadFiles 라는 middleware를 만들었다.
dest = destination 즉 파일이 저장되는 경로를 지정해주는 것이다.

3. using multer in router

//userRouter.js

userRouter
  .route("/edit")
  .all(protectorMiddleware)
  .get(getEdit)
  .post(uploadFiles.single("avatar"), postEdit); 

위 라우터에는 두개의 middleware가 들어가있다.
1. protectorMiddleware
2. uploadFiles.single("avatar")

1번은 로그인한 유저만 url 접근이 가능하게 하는 middleware로

// middleware.js

export const protectorMiddleware = (req, res, next) => {
 if (req.session.loggedIn) {
   return next();
 } else {
   return res.redirect("/login");
 }
};

로그인시 부여하는 session.loggedIn = true 를 받아야 접근 가능하도록 했다. 그렇지 않으면 로그인페이지로 이동하게 된다.

2번은 multer middleware로 postEdit 컨트롤러가 실행되기 전에 거쳐가게 되며, single = 파일을 한개씩 업로드 할 수 있으며, ("avatar") = input name이 "avatar"인 곳에서 업로드되는 파일을 받는다.

이렇게 postEdit으로 보내진 file은 req.file 로 확인할 수 있다.

4. controller

// userController.js

export const postEdit = async (req, res) => {
  const {
    session: {
      user: { _id, avatarUrl },
    },
    file,
  } = req;
  console.log(file);
  const updatedUser = await User.findByIdAndUpdate(
    _id,
    {
      avatarUrl: file ? file.path : avatarUrl,
    },
    { new: true }
  );
  req.session.user = updatedUser;
  res.redirect("/users/edit");
};

만약 유저가 프로필을 변경할 때 사진을 변경하지 않아도 기존 데이터를 유지해주기 위해 avataeUrl: file ? file.path : avatarUrl, 해주었다.
file : req.file 에서 file이 존재한다면 req.file.path를 새로 저장할 것이고 그렇지 않으면 기존 로그인 정보대로 req.session.user.avatarUrl을 저장할 것이다.

console.log(file) ↓↓↓↓↓↓↓↓↓↓↓

tip. 서로 다른 사용자가 같은 이름의 파일을 업로드 해도 multer가 임의의 파일명으로 변경해주기 때문에 괜찮다.

5. avatar img 보여주기

업로드한 이미지의 path는 uploads/... 의 구조를 가지므로 express에 해당 라우터를 열어줘야한다.

app.use("/uploads", express.static("uploads")); // /uploads url에서 uploads 폴더의 내용을 보여달라는 뜻

img 보여주는 링크는 1번 pug 파일 확인하기!

profile
T.T

0개의 댓글