[nodejs] fetch로 multer fileupload 시 req.file undefined

코덩이·2022년 6월 10일
0

백엔드

1. multer 미들웨어 코드를 잘 작성하였는가

  • Multer 모듈을 import하여 설정 파일을 작성한다.
import multer from "multer";
import path from "path";

const fileStorage = multer.diskStorage\\({
  // 저장 폴더 위치
  destination: (req, file, cb) => {
    cb(null, "upload/");
  },
  //파일이름
  filename: (req, file, cb) => {
    cb(null, file.originalname);
  },
});
export const multerUpload = multer({
  storage: fileStorage,
  limits: {
    fileSize: 20 * 1024 * 1024, // 20MB 로 제한
  },
});

export default multerUpload;

2. destination에 작성한 이름의 폴더가 존재하지 않는지 확인한다.

  • 폴더가 미리 생성되어 있지 않으면 저장이 되지 않고 500 오류가 발생한다.

  • 이런 불상사를 막기위해 fs 모듈을 이용하여 폴더를 생성하는 코드를 작성해 놓으면 편하다.

import multer from "multer";
import path from "path";
import fs from "fs";

try {
  fs.readdirSync("upload");
} catch (err) {
  console.error("upload 폴더가 없습니다. 폴더를 생성합니다.");
  fs.mkdirSync("upload");
}

const fileStorage = multer.diskStorage({
  // 저장 폴더 위치
  destination: (req, file, cb) => {
    cb(null, "upload/");
  },
  //파일이름
  filename: (req, file, cb) => {
    cb(null, file.originalname);
  },
});
export const multerUpload = multer({
  storage: fileStorage,
  limits: {
    fileSize: 20 * 1024 * 1024, // 20MB 로 제한
  },
});

export default multerUpload;

3. multer 미들웨어를 router에 잘 작성하였는가

  • multer 미들웨어 설정을 한 코드를 작성하여 file 데이터가 필요한 router의 아래 위치에 넣어야한다.
  • 또한 괄호안의 "file" 은 태그의 name과 이름이 같아야 한다.
router.post("/video", multerUpload.single("file"), async (req, res, next) => {
  console.log(req.body);
  console.log(req.file);
}

프론트엔드

1.formData를 잘 넘겼는가

  • 태그를 사용하지 않으니 FormData 객체를 사용해야한다.
  • 참고로 append된 데이터들은 FormData 특성상 console.log에 보이지 않으니 formData.entries() 를 사용하는 다른 방식을 찾아보길 바란다.
const videoFetch = async () => {
    // 영상 데이터 가져오기
    const videoData = document.getElementById("inputVideo").files[0];

    setVideoFile(videoData.name);

    // formData 객체에 append
    const formData = new FormData();
    formData.append("file", videoData);

 }

2. fetch의 Header 는 껍데기만 빼고 없애야한다.

  • 위의 모든 것들을 시도해본 사람들이 header 때문에 고생한다.
  • form를 태그를 사용하지 않는다면 따로 'multipart/form-data'를 작성할 필요 없이 기본으로 아래와 같은 데이터가 담긴다.
Content-Typy : multipart/form-data; boundary=----WebKitFormBoundarytgngAeRWcdblG9zH

  • 만약 'multipart/form-data' 를 명시한다면 뒤의 'boundary ~' 가 존재하지 않는다는 오류가 발생한다.
  • header를 완전히 지운경우 500 오류가 발생하는 것을 확인하였다.
  • 따라서 header 껍데기는 놔둔 후 내용을 지우는 방식으로 마지막 오류를 해결하였다.
  • 몇몇 블로그에서 fetch를 이용하는 경우 "Content-Type": "application/x-www-form-urlencoded" 를 header에 작성하라고 하는데 이는 현재 문제를 발생시킨다.
  • 결론: header를 껍데기만 남기고 지우자.
  • 참고: 몇달전에는 껍데기를 지워도 작동했는데 원인을 모르겠다.
  • 22.06.15 추가: 갑자기 500 오류로 fetch가 실행되지 않아서 header를 전부 주석처리 했더니 잘 작동한다. 누군가 원인을 안다면 알려주시길. 부탁드린다.
const videoFetch = async () => {
    // 영상 데이터 가져오기
    const videoData = document.getElementById("inputVideo").files[0];

    setVideoFile(videoData.name);

    // formData 객체에 append
    const formData = new FormData();
    formData.append("file", videoData);

    // 비디오 저장 fetch
    const videoRes = await fetch(`http://localhost:5050/mypage/video`, {
      method: "POST",
      headers: {
        // "Content-Type": "application/x-www-form-urlencoded",
      },
      body: formData,
	});
 }
profile
개발공부중

0개의 댓글