Multer: 파일 저장 미들웨어

- mongoDB에 file 원본을 저장하지 않고, file의 location을 저장할 것이다.
- Multer라는 middleware를 통해 중간에 upload하려는 파일의 정보를 가지고 올 수 있다.
- Multer을 통해 반환받은 file의 URL을 mongoDB에 저장한다.
multer
- multer는 파일 저장을 위해 사용되는 node.js middleware입니다.
- multer를 이용해서 파일을 저장하면 파일명이 임의로 바뀌고 문서형태로 변환되게 됩니다.
npm install multer
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/*")
input(type="text", name="title", required = true)
textarea(name="description", placeholder="Description", required=true)
input(type="submit", value="Upload now")
- video file만 Upload하게 파일 확장자에 대한 제한을 건다. input의 accept property를 사용한다.
- 와 같은 형식을 사용하면 됩니다.
우리는 video를 원하기 때문에 라고 하겠습니다. - multer를 사용하기 위해선 form의 속성인 enctype(인코딩 타입)이 multipart/form-data 이어야 합니다. enctype이 지정되어 있지 않으면 저장할 수 없으니 유의합니다.
middlewares.js
import multer from "multer";
const multerVideo = multer({dest:"videos/"});
// 'videos/'로 디렉토리를 지정한다. videos/라는 뜻은 현재 폴더 밑에 videos이다.
// '/videos/'로 하면 컴퓨터 루트폴더로부터의 폴더경로를 의미하게 되므로 주의
// 폴더는 multer가 자동으로 생성하므로 신경쓰지 않아도 된다.
export const uploadVideo = multerVideo.single("videoFile")
어떤 이름의(form에서 name 속성) 파일을 몇개 업로드 할지도 정해야한다.
- 이름은 form내부 file type input의 name과 동일해야 합니다.
- single의 의미는 하나의 파일을 업로드한다는 뜻이다.
videoRouter.js
import {uploadVideoMiddleware} from '../middlewares';
videoRouter.post(routes.upload, uploadVideoMiddleware, postUpload);
post method로 /upload로 요청하면 응답으로 postUpload가 실행되는데요. postUpload가 실행되기전에 파일을 업로드하기위해 uploadVideoMiddleware를 사이에 넣어줍니다. 그러면 이 middleware가 저장한 파일에 대한 정보를 req.file에 넣은 후 postUpload를 실행시킵니다. 참고로 middleware끼리는 res,req를 공유합니다.
videoController
postUpload 함수에 대한 코드를 살펴보겠습니다. multer는 저장한 파일에 대한 정보를 req의 file에 담아서 보냅니다. 아래의 코드로 우리는 file을 받을 수 있습니다.
export const postUpload = (req, res) => {
const {file} = req;
console.log(file);
}
upload 페이지에서 업로드를 하고 콘솔을 확인하면 아래와 같습니다.

업로드한 file에 대한 정보를 볼 수 있네요. 이 중에서 눈여겨볼 것은 바로 path 입니다. 우리가 Video Model을 만들때 우리는 database에 file 자체를 저장하는 것이 아니라 fileURL을 저장할 것이라고 하였죠. 이 fileURL에 해당하는 것이 바로 path입니다. 이제 이 정보를 이용하여 데이터베이스에 Video element를 추가해보겠습니다.
- Video.create({})
Video model의 메소드 create에 의하여 element 객체를 전달하여 실행하면 해당 element를 데이터베이스에 저장하고 저장된 video 객체를 반환해줍니다. - newVideo.id
redirect하는 부분을 보면 Video model schema로 id를 적어준적은 없지만 mongoDB 자체적으로 id를 부여하기 때문에 id 속성을 사용할 수 있습니다._id로 하여도 동일합니다.
import Video from '../models/Video';
export const postUpload = async(req, res) => {
const {
body : { title, description },
file : { path }
= req;
const newVideo = await Video.create({
fileUrl : path,
title,
description });
res.redirect(routes.videoDetail(newVideo.id));
}