middleware를 통해 중간에 upload하려는 파일을 가지고 올 수 있다는 얘기를 했던게 기억이 나시나요? 기억이 나지 않더라도 오늘 다시 되새기며 공부해보겠습니다.
multer는 파일 저장을 위해 사용되는 node.js middleware입니다. multer를 이용해서 파일을 저장하면 파일명이 임의로 바뀌고 문서형태로 변환되게 됩니다.
multer를 사용하기 위해선 form의 속성인 enctype(인코딩 타입)이 multipart/form-data
이어야 합니다. enctype이 지정되어 있지 않으면 저장할 수 없으니 유의합니다.
<form enctype="multipart/form-data">
%npm install multer
를 터미널에 입력
youtube
|views
*|upload.pug
*|middlewares.js
|routers
*|videoRouter.js
video file을 upload하라고 form을 만들어 두었는데 image 파일을 올리면 안되겠죠? upload 가능한 파일 확장자에 대한 제한을 위해서는 input의 accept property를 사용합니다.
<input type="file" accept="파일 확장자|audio/*|video/*|image/*|미디어 타입">
와 같은 형식을 사용하면 됩니다.
우리는 video를 원하기 때문에 <input type="file" accept="video/*">
라고 하겠습니다.
block content
form(action=routes.upload, method="post", enctype="multipart/form-data")
input(type="file", accept="video/*");
//나머지 생략
middleware로 사용하기 위해서 configuration이 필요하므로 middlewares 파일에서 선언하고 설정을 해주도록 하겠습니다.
videos/
로 저장 디렉토리를 지정해줬으므로 프로젝트 폴더에 videos 폴더를 하나 만들어야합니다. videos/
라는 뜻은 현재 폴더 밑에 videos라고 생각하면 됩니다. /videos/
로 하면 컴퓨터 루트폴더로부터의 폴더경로를 의미하게 되므로 주의합니다. (폴더는 multer가 자동으로 생성하므로 신경쓰지 않아도 됩니다.)import multer from 'multer';
const uploadVideo = multer({dest:'videos/'});
export const uploadVideoMiddleware = uploadVideo.single('videoFile');
/*다른 middleware 생략*/
post method로 /upload
로 요청하면 응답으로 postUpload가 실행되는데요. postUpload가 실행되기전에 파일을 업로드하기위해 uploadVideoMiddleware를 사이에 넣어줍니다. 그러면 이 middleware가 저장한 파일에 대한 정보를 req.file에 넣은 후 postUpload를 실행시킵니다. 참고로 middleware끼리는 res,req를 공유합니다.
import {uploadVideoMiddleware} from '../middlewares';
/*생략*/
videoRouter.post(routes.upload, uploadVideoMiddleware, postUpload);
이제 마지막으로 postUpload 함수에 대한 코드를 살펴보겠습니다. multer는 저장한 파일에 대한 정보를 req의 file에 담아서 보냅니다. 아래의 코드로 우리는 file을 받을 수 있습니다.
export const postUpload = async(req, res) => {
const {file} = req;
console.log(file);
}
upload 페이지에서 업로드를 하고 콘솔을 확인하면 아래와 같습니다.
업로드한 file에 대한 정보를 볼 수 있네요. 이 중에서 눈여겨볼 것은 바로 path 입니다. 우리가 Video Model을 만들때 우리는 database에 file 자체를 저장하는 것이 아니라 fileURL을 저장할 것이라고 하였죠. 이 fileURL에 해당하는 것이 바로 path입니다. 이제 이 정보를 이용하여 데이터베이스에 Video element를 추가해보겠습니다.
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));
}