multer 사용하기

file 업로드 후 url을 반환하는 미들웨어

npm install multer

1. 업로드 하는 폼 태그는 multipart/form-data 형식

폼 태그에 enctype="multipart/form-data" 추가한다.
(* method는 전송 방식, action은 전송 목적지, enctype은 전송되는 데이터 형식을 설정)
(* enctype 중 multipart/form-data 는 파일이나 이미지를 서버로 전송할 경우 이 방식을 사용)

upload.pug

form(action=`/videos${routes.upload}`, method="post", enctype="multipart/form-data")
    label(for="file") video File
    input(type="file", id="file", name="videoFile" required=true, accept="video/*")

2. multer 연결

multer를 임포트 시켜주고 multer 함수를 넣고 도착지(destination=desc)인 경로를 넣으면 해당 경로에 파일이 업로드 된다.
(* single은 오직 하나의 파일만 업로드 할 수 있는 걸 의미)
(* single 안의 이름은 폼 태그의 파일 업로드 인풋 태그의 name="videoFile" 과 같아야함)

middlewares.js

import multer from "multer";
const multerVideo = multer({dest: "uploads/videos/"});
...
export const uploadVideo = multerVideo.single("videoFile");

3. 라우터에 multer 연결

파일을 업로드하면 서버에 있는 폴더(uploads/videos/)에 업로드가 되고 postUpload 이라는 함수는 해당 파일에 접근한다.
(* 파일 방식이 아닌 URL 방식으로 접근 = multer의 역할로 인해)

videoRouter.js

...
videoRouter.post(routes.upload, uploadVideo, postUpload);
...

4. 컨트롤러에서 multer 가 준 경로로 비디오 정보(models) 담기

controllers/videoController.js

import routes from "../routes";
import Video from "../models/Video";
...
export const postUpload = async (req,res) => {
    // multer에서 준 file path = 새로운 비디오 fileUrl 연결
    const { body : { title, description }, file : { path }} = req;
    console.log(body, file)
    const newVideo = await Video.create({
        fileUrl : path,
        title : title,
        description : description
    });

    // To do : upload and save video
    res.redirect(routes.videoDetail(newVideo.id));
}

models/Video.js

import mongoose from "mongoose";

const VideoSchema = new mongoose.Schema({
  fileUrl: {
    type: String,
    required: "File URL is required"
  },
  title: {
    type: String,
    required: "Tilte is required"
  },
  description: String,
  views: {
    type: Number,
    default: 0
  },
...
});

const model = mongoose.model("Video", VideoSchema);
export default model;

++
Video 모델에 있는 변수들이 홈 화면의 변수와 연결되어 있는지 확인

home.pug

extends layouts/main.pug
include mixins/videoBlock

block content
    .videos
        each item in videos
            +videoBlock({
                id : item.id,
                title : item.title,
                views : item.views,
                videoFile : item.fileUrl,
            })