multer 사용하기

김무연·2023년 12월 15일

Backend

목록 보기
41/49
post-thumbnail

멀티파트 데이터 형식

form 태그의 enctype이 multipart/from-data인 경우

  • 기존의 body-parser로는 요청 본문을 해석할 수 없음
  • multer 패키지 필요

프론트에서 post로 데이터를 보낼 때, 이미지, 파일등 여러가지를 보낼 대 form-data 형식으로 보냄

<form action="/upload" method="post" enctype="multipart/from-data">
	<input type="file" name="image" />
    <input type="text" name="title" />
</form>

위 처럼 데이터가 날라오게 된다. 이를 직접 해석하기에는 어려우니 multer를 사용

multer 설정하기

multer 함수를 호출

  • storage는 저장할 공간에 대한 정보
  • diskStorage는 하드디스크에 업로드 파일을 저장한다는 것
  • destination은 저장할 경로를 done의 두 번째 인수로 넘기면 됨
  • filename은 저장할 파일명(파일명+날짜+확장자 형식)을 done으로 넘기면 됨
  • limits는 파일 개수나 파일 사이즈를 제한할 수 있음.
  • 실제 서버 운영 시에는 서버 디스크 대신에 S3같은 스토리지 서비스에 저장하는 게 좋음 ( 서버 디스크 용량을 많이 잡아먹는 것을 방지 )
try {
  fs.readdirSync('uploads');
} catch (error) {
  console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.');
  fs.mkdirSync('uploads');
}

첫 번째로 위 코드를 보면 일단 uploads 폴더를 만들도록 되어 있다. 여기서 Sync를 서버인데도 쓰는 이유는, 일단 폴더가 있는지 없는지 확인을 먼저해야 하기 때문에, 동기적으로 작동되어 제일 먼저 실행되게 Sync를 사용 해준다.

const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, done) {
      done(null, 'uploads/');
    },
    filename(req, file, done) {
      const ext = path.extname(file.originalname);
      done(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
  limits: { fileSize: 5 * 1024 * 1024 },
});

이후 multer를 호출해 storage 어디에 저장해둘지 기입하는데, 현재는 서버 디스크에 저장되도록 diskStorage라고 설정되어 있다. 하지만 실무에서는 파일들의 용량이 큰 것을 disk 서버에 저장하면 낭비가 되니 s3같은 스토리지에 저장되게 한다

이후 filename으로 어떠한 이름으로 저장될지 지정하는데, ext로 확장자 이름을 추출하여, Date.now()와 같이 서로 같은 이름 중복을 방지하게 이름을 추가해주고, 마지막에 확장자를 넣어, 파일이름을 살짝 바꿔 준다.

done(인자1, 인자2) 인데 인자1은 에러가 났을 때, 에러 처리 미들웨어로 넘기는 것이고, 인자2는 에러가 아닐 때, 성공할 때의 값이다.

limits는 파일 개수, 파일 용량 을 제한한다.

app.post('/upload', upload.single('image'), (req, res) => {
  console.log(req.file);
  res.send('ok');
});

app.use(upload.single('image'))를 해도 되긴 하지만, 업로드는 모든 메서드, 라우터에서 일어나는 것이 아닌 특정 메서드, 라우터에서만 일어나기 때문에 post메서드에서만 upload.single('image')를 해준다.

upload에는 single과 none, array, fields 미들웨어 존재

  • single은 하나의 파일을 업로드할 때, none은 파일을 아예 업로드하지 않을 때
  • req.file 안에 업로드 정보 저장

  • 만약 배열로 들어오면, 위와 같은 업로드 정보 객체가 배열에 여러개 담기게 된다.
  • array와 fields는 여러 개의 파일을 업로드 할 때 사용
  • array는 하나의 요청 body 이름 아래 여러 파일이 있는 경우
  • fields는 여러 개의 요청 body 이름 아래 파일이 하나씩 있는 경우
  • 두 경우 모두 업로드된 이미지 정보가 req.files 아래에 존재

fields일 때

app.post('/upload', upload.fields([{name : 'image1'}, {name: 'image2]), (req, res) => {
  console.log(req.file);
  res.send('ok');
});

none 일 때

  • 이미지는 아니지만 폼 데이터로 업로드 하여 여러가지 업로드 할 때, 이럴 때도 마찬가지로 Form data형식으로 데이터가 옴
  • 이미지 파일은 따로 안오게 되니깐, req.file은 존재하지 않는다, req.body 에 정보가 담겨있게 된다.
profile
Notion에 정리된 공부한 글을 옮겨오는 중입니다... (진행중)

0개의 댓글