이미지, 동영상 등을 비롯한 여러 가지 파일들을 멀티파트 형식으로 업로드할 때 사용하는 미들웨어이다.
멀티파트 형식이란 enctype이 multipart/form-data 인 폼을 통해 업로드하는 데이터의 형식을 의미한다.
Express로 서버 구축시 가장 많이 사용되는 미들웨어
미들웨어란?
요청(request)과 응답(response) 사이에서 중간다리 역할을 하는 SW
ex1) request의 body를 서버에서 읽을 수 있도록 도와주는 "body-parser"
ex2) request의 file에서 보내는 파일 정보를 확인할 수 있도록 도와주는 "multer"
ex3) static 파일 설정을 도와주는 app.use(express.static(~~))
npm install 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 미들웨어를 사용한다.
(아래코드에선 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 // 파일 크기
}
여러개의 파일을 업로드 한다면 파일 타입의 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 👨💻:티스토리]