Express - Multer 라이브러리
multer는 Node Express 서버에서 파일 업로드를 위한 미들웨어이다. HTML에서 Form데이터를 처리하거나 Ajax를 통해 클라이언트에서 서버로 파일을 업로드할 수 있다.
1. multer 설치
> npm i multer
2. multer(opts)
const multer = require("multer");
속성 | 설명 |
dest or storage | 파일이 저장될 위치 |
fileFilter | 어떤 파일을 허용할지 제어하는 함수 |
limits | 업로드 된 데이터의 한도 |
preservePath | 파일의 base name 대신 보존할 파일의 전체 경로 |
3. 업로드 규칙
1) strage / dest
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/data'); //파일 저장 경로
},
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`); //파일 이름
}
})
// 파일 저장 경로는 /uploads/data 저장
// 파일 이름은 현재시간-기존파일이름.기존확장자
스토리지는 업로드 파일을 디스크에 저장하기 위해 모든 제어 기능을 제공.
destination, filename의 두 가지 옵션이 있다. destination 옵션은 어디 폴더에 저장할지를 정한다. (사용 방법은 위 코드 참고) filename은 말 그대로 어떤 이름으로 저장할지를 설정. 아무런 설정이 없다면 랜덤 한 값으로 설정되며, 확장자까지 사라지므로 주의해야 함. file에는 아래의 정보를 포함하고 있어 참고하여 사용
속성 | 설명 | 기본값 |
fieldname | 폼에 정의된 필드 명 | |
originalname | 사용자가 업로드한 파일 명 | |
encoding | 파일의 엔코딩 타입 | |
mimetype | 파일의 Mime 타입 | |
size | 파일의 바이트(byte) 사이즈 | |
destination | 파일이 저장된 폴더 | DiskStorage |
filename | destination 에 저장된 파일 명 | DiskStorage |
path | 업로드된 파일의 전체 경로 | DiskStorage |
buffer | 전체 파일의 Buffer | MemoryStorage |
규칙 없이 단순 경로만 사용 할 경우 dest 옵션에 경로만 지정하여 사용
const upload = multer({ dest: 'uploads/' })
2) Limits
Limits는 파일의 크기 제한을 지정하는 객체로 아래의 속성들을 알맞게 사용하여 업로드 파일의 용량을 제한하면 된다. 기본적으로 DoS 공격을 보호하기 위해 설정해주는 편이 좋다.
속성 | 설명 | 기본값 |
fieldNameSize | 필드명 사이즈 최대값 | 100 bytes |
fieldSize | 필드값 사이즈 최대값 | 1MB |
fields | 파일형식이 아닌 필드의 최대 개수 | 무제한 |
fileSize | multipart 형식 폼에서 최대 파일 사이즈(bytes) | 무제한 |
files | multipart 형식 폼에서 파일 필드의 최대 개수 | 무제한 |
parts | For multipart forms, the max number of parts (fields + files) | 무제한 |
headerPairs | multipart 형식 폼에서 파싱할 헤더의 key=>value 쌍의 최대 개수 | 2000 |
4. upload 선언
const upload = multer({ storage : storage, limits: { fileSize: 10 * 1024 * 1024 } }); //크기 제한 : 10MB
지금까지 만든 storage와 limits 규칙들을 가지고 upload를 선언
5. 업로드 받기
//Front
<input type="file" name="profile" id="upload-input"/>
// Back
app.post('/upload/profile', upload.single('profile'), (req, res)=> {
console.log(req.file);
res.status(200).send("ok!");
});
.single(filedname) : filedname에 명시된 하나의 파일을 업로드받는다. input 태그에 name 속성을 지정해주면 된다. 업로드 후 req.file 에 저장
.array(filedName, [, maxCount]) : 복수의 파일을 업로드받을 경우 사용 하며, filename에 명시된 파일 전체를 배열 형태로 전달받고 maxCount로 개수의 제한을 설정한다. single과 같이 req.file 에 저장
.feilds(fields) : 인자에 명시된 여러 파일을 전달 받음.
[
{ name: 'avatar', maxCount: 1 },
{ name: 'gallery', maxCount: 8 }
]
.any() : 모두 허용
6. fileFilter 적용하기
const fileFilter = (req, file, cb) => {
// 이 함수는 boolean 값과 함께 `cb`를 호출함으로써 해당 파일을 업로드 할지 여부를 나타낼 수 있습니다.
// 이 파일을 거부하려면 다음과 같이 `false` 를 전달합니다:
cb(null, false)
// 이 파일을 허용하려면 다음과 같이 `true` 를 전달합니다:
cb(null, true)
// 무언가 문제가 생겼다면 언제나 에러를 전달할 수 있습니다:
cb(new Error('I don\'t have a clue!'))
}
fileFilter는 업로드된 파일의 유효성 검사를 도와준다. 아래 코드는 이미지 파일만 업로드 가능하도록 유효성 작성된 코드이다.
const fileFilter = (req, file, cb) => {
const typeArray = file.mimetype.split('/');
const fileType = typeArray[1];
if (fileType == 'jpg' || fileType == 'png' || fileType == 'jpeg' || fileType == 'gif' || fileType == 'webp') {
req.fileValidationError = null;
cb(null, true);
} else {
req.fileValidationError = "jpg,jpeg,png,gif,webp 파일만 업로드 가능합니다.";
cb(null, false)
}
}
필터의 적용은 아래와 같이 upload를 선언할 때 필터를 지정해서 적용
const upload = multer({
storage : storage,
fileFilter : fileFilter,
limits: {
fileSize: 10 * 1024 * 1024 //크기 제한 : 10MB
}
});
7. 테스트
전혀다른 확장자인 pptx 파일을 업로드했을 경우 위와 같은 에러가 출력된다. 물론 프론트 단에서 <input> 태그에서 허용 가능한 확장자를 지정해 줄 수 있지만 백엔드 단에서도 유효성 체크를 해주는 것이 바람직하다.
<input type="file" name="profile" accept="image/gif, image/jpeg, image/png, image/webp" />