[새싹x코딩온] 풀스택 과정 6주차 파일업로드

김성민·2024년 2월 2일

multer 모듈

이미지, 동영상 등을 비롯한 여러 가지 파일들을 멀티파트 형식으로 업로드할 때 사용하는 미들웨어이다.
멀티파트 형식이란 enctype이 multipart/form-data 인 폼을 통해 업로드하는 데이터의 형식을 의미한다.
Express로 서버 구축시 가장 많이 사용되는 미들웨어

미들웨어란?
요청(request)과 응답(response) 사이에서 중간다리 역할을 하는 SW

ex1) request의 body를 서버에서 읽을 수 있도록 도와주는 "body-parser"
ex2) request의 file에서 보내는 파일 정보를 확인할 수 있도록 도와주는 "multer"
ex3) static 파일 설정을 도와주는 app.use(express.static(~~))

multer 모듈 설치

npm install multer

app.js multer 설정

const multer = require("multer");
const upload = multer({
  dest: "uploads/",
});
/* multer detail 설정
-storage : 저장공간에 정보
    diskStorage : 파일을 저장하기 위한 모든 제어 기능 제공
    - destination : 저장경로
    - filename : 파일 이름 관련 정보
-limits : 파일 제한 관련 정보
    fileSize : 파일 사이즈를 바이트 단위로 제한
*/
const uploadDetail = multer({
  storage: multer.diskStorage({
    destination: function (req, file, done) {
      done(null, "uploads/");
    },
    filename: function (req, file, done) {
      const extension = path.extname(file.originalname); // path 모듈 사용시 require 필요
      done(null, path.basename(file.originalname, extension) + Date.now() + extension);
    },
  }),
  limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
});

multer에 넣은 인수들은 다음과 같다.

먼저 storage 속성에 어디에 (destination) 어떤 이름으로 (filename) 저장할지를 넣었다.
두 함수의 req 매개변수에는 요청에 대한 정보, file 객체에는 업로드한 파일에 대한 정보가 있으며, done 매개변수는 함수이다.

done() 함수는 첫 번째 인수에는 에러가 있다면 에러를 넣고, 두 번째 인수에는 실제 경로나 파일 이름을 넣어주면 된다.
req나 file의 데이터를 가공해 done으로 넘기는 식이다.

현재 설정으로는 uploads라는 폴더에 [파일명 + 현재시간.확장자] 파일명으로 업로드하는 것을 볼 수 있다.
limits 속성에는 업로드에 대한 제한 사항을 걸어두었다.
위 예제에서는 파일 크기를 5MB (5 1024 1024 byte) 로 제한해두었다.

다만 위 설정을 실제로 활용하기 위해선 서버에 uploads 폴더가 꼭 존재해야 한다.
없다면 직접 만들어주거나, fs 모듈로 서버를 시작할 때 생성하는 방식이 있다.

--- fs 모듈로 서버시작시 생성하는 방법 ---

const path = require("path");
const fs = require("fs");
const multer = require("multer");

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

---dest 속성 사용시에는 자동으로 생성된다 ----

const upload = multer({
  dest: "uploads/",
});

라우터에서 사용

upload.single()

설정이 끝난다면 위에서 선언해준 upload 객체 변수가 생기게 되는데, 이 안에 다양한 종류의 미들웨어가 존재한다.
파일을 하나만 업로드하는 경우에는 single 미들웨어를 사용한다.
(아래코드에선 uploadDetail이란 이름으로 객체변수 선언)

app.post("/upload", uploadDetail.single("userfile"), function (req, res) {
    console.log(req.file);
});

single 미들웨어를 라우터 미들웨어(콜백함수) 앞에 넣어두면 multer 설정에 따라 파일 업로드 후 req.file 객체가 생성된다.
인수는 input 태그의 name이나 폼 데이터의 키와 일치하게 넣으면 된다.
업로드가 성공하면 결과는 req.file 객체 안에 들어간다.
req.file 객체는 다음과 같이 생겼다.

{
fieldname: 'userfile', // 폼에 정의한 name 값
originalname: 'small_img.png', // 원본 파일명
encoding: '7bit', // file encoding type
mimetype: 'image/png', // 파일 타입
destination: 'uploads/', // 파일 저장 경로
filename: '22e7991be4350c3ad4887339670f0b3b', // 저장된 파일이름
path: 'uploads/22e7991be4350c3ad4887339670f0b3b', // 경로포함된 파일 이름
size: 2441 // 파일 크기
}

upload.array()

여러개의 파일을 업로드 한다면 파일 타입의 input 태그에 multiple 속성을 추가하면 여러개의 파일을 올릴 수 있는데. 이때 사용하는 메서드는 upload.array()를 사용한다

views.ejs

    <h2>파일 여러개 업로드1</h2>
    <p>하나의 input에 여러개 파일 업로드</p>
    <form action="/uploads/array" method="post" enctype="multipart/form-data">
      <input type="file" name="multifiles" multiple />
      <br />
      <br />
      <input type="text" name="title" placeholder="사진제목을 입력해주세요" />
      <br />
      <br />
      <button type="submit">업로드</button>

app.js

app.post("/uploads/array", uploadDetail.array("multifiles"), function (req, res) {
  // 여러개 1
  console.log(req.files); //files로 수정, 배열로 요청됨, 하나의 파일만 업로드해도 배열
  console.log(req.body);
  res.send("업로드 완료");
});

upload.field()
한번에 파일을 여러 개 업로드하는게 아닌, 따로따로 업로드를 여러개 한다면,
즉, input 태그나 폼 데이터의 키가 다른 경우엔 fields 미들웨어를 사용한다.
예를 들어 아래와 같을 경우,

이런식으로 사용한다

app.post(
  "/uploads/fields",
  uploadDetail.fields([{ name: "file1" }, { name: "file2" }, { name: "file3" }]),
  function (req, res) {
    // 여러개 2
    console.log(req.files);
    /* 
    {file1:[{}], file2:[{}], name속성:[{},{},...]} */
    console.log(req.body);
    res.send("업로드 완료");
  }
);

++추가 upload.none()
특수한 경우에, 파일이 아님에도 멀티파트 형식으로 업로드하는 경우가 있다.
new FormData()로 데이터를 보낼때도 있기 때문이다.
그 경우 none 미들웨어를 사용한다.
파일은 없지만 멀티파트 형식이기 때문에 함수가 따로 존재하는 것이다.

참고자료 :
https://inpa.tistory.com/entry/EXPRESS-📚-multer-미들웨어 [Inpa Dev 👨‍💻:티스토리]

0개의 댓글