tech.junha.kr

Multer: 파일 저장 미들웨어

  1. mongoDB에 file 원본을 저장하지 않고, file의 location을 저장할 것이다.
  2. Multer라는 middleware를 통해 중간에 upload하려는 파일의 정보를 가지고 올 수 있다.
  3. 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));
}