Back
Featured image of post [Node.js] multer 사용법

[Node.js] multer 사용법

multer를 이용한 파일 처리

multer


multer

요청 타입이 multeipart/form-data인 경우 multer를 이용해 받을 수 있다.

설치하기

npm i multer

사용방법

multer모듈을 임포트 해주고 미들웨어로 사용하기 위해 여러 설정을 해준다.

const multer = require('multer');
const path = require('path');

// 디렉토리 없을 경우 생성해주는 예외 처리
// (server listen 전 단계 이므로 동기식 코드로 해도 무방)
try {
    fs.readdirSync('assets');
} catch (error) {
    console.error('not exist directory.');
    fs.mkdirSync('assets');
}

const upload = multer({
    // 파일 저장 위치 (disk , memory 선택)
    storage: multer.diskStorage({
        destination: function (req, file, done) {
            done(null, 'assets/');
        },
        filename: function (req, file, done) {
            const ext = path.extname(file.originalname);
            done(null, path.basename(file.originalname, ext) + Date.now() + ext);
        }
    }),
    // 파일 허용 사이즈 (5 MB)
    limits: { fileSize: 5 * 1024 * 1024 }
});

storage에서 파일을 저장 할 경로와 이름을 설정 할 수 있는데, file인수에서 다음 속성으로 파일 정보를 얻을 수 있다.

  • fieldname : html 폼에 정의된 필드 명
  • originalname : 사용자가 업로드 한 파일 명
  • size : 파일 사이즈 (byte 단위)
  • mimetyp : 파일 타입 (밈 타입)
{
    "fieldname": "file",
    "originalname": "jortu.png",
    "encoding": "7bit",
    "mimetype": "image/png",
    "destination": "assets/",
    "filename": "jortu1641367168859.png",
    "path": "assets\\jortu1641367168859.png",
    "size": 381172
}

파일 업로드를 사용 할 라우터에 미들웨어 함수로 붙이면 된다. 작성한 함수에 메서드로 single을 붙이고 있는데 업로드 방식에 따라 메서드 체이닝이 다르다. single메서드는 단일 파일로 전달 받을 때 사용한다.

app.post('/photo', upload.single('file'), function (req, res, next) {
    //업로드 정보 확인
    console.log(req.file);
    res.send('upload success.');
});

웹브라우저에서 통신 되는지 확인하려고 input file 필드 한개를 주고 jQuery로 확인해 보았다.

<body>
    <h2>file upload Test</h2>
    <hr>
    <input type="file" name="file" id="uploadFile">
</body>
<script>
    $(function () {
        function uploadImage() {
            const formData = new FormData();
            formData.append('file', $('#uploadFile')[0].files[0]);
            console.log(JSON.stringify($('#uploadFile')[0].files[0]));
            $.ajax({
                type: 'POST',
                url: '/photo',
                data: formData,
                processData: false,
                contentType: false,
                success: function (json) {
                    console.log(JSON.stringify(json));
                }
            });
        }

        $('#uploadFile').change(function () {
            return uploadImage();
        })
    });
</script>

multer

multer 설정

multer 호출 시 4개의 속성으로 옵션 객체를 생성할 수 있다.

const upload = multer({
	storage: multer.diskStorage({..}),
	limits : {..},
	fileFilter : function(req, file, cb){ //..code }
});

storage (dest)

파일 저장에 관련한 옵션이다. storage 또는 dest 속성으로 정의한다. destination은 업로드 한 파일을 어디에 저장할 지 결정하고, filename은 저장 할 파일의 이름을 결정한다. (만약 filename에 대한 설정이 없다면 랜덤한 파일 이름으로 저장된다고한다..)

multer.memoryStorage()는 임시 메모리에 파일을 저장할 때 사용한다. 어떠한 설정도 필요가 없으며 용량이 많은 파일이나 다수의 파일을 업로드 하는 경우에는 메모리 부족이 발생할 수 있다. (주로 클라우드 서비스에 파일을 올릴 때 임시 보관 용도로 사용한다고 한다.)

const diskStorage = multer.diskStorage({
    //물리 디스크
    destination: function (req, file, done) {
        done(null, '/path');
    },
    filename: function (req, file, done) {
        done(null, file.fieldname + '-' + Date.now());
    }
});

const memoryStorage = multer.memoryStorage(); //임시 메모리

const upload = multer({
    storage: diskStorage
});

limits

파일 관련한 크기를 제어하는 속성이다. 단순히 파일 용량 뿐만 아니라 필드 이름에 대한 사이즈도 제어할 수 있다. 최대한 엄격하게 관리해야 혹시나 받을 수 있는 외부 공격에 대해 도움이 될 수 있다.

  • fieldNameSize : 필드 이름 최대 값 (기본 : 100 Byte)
  • fileSize : 파일 크기 최대 값 (기본 : 무제한)
  • files : 파일 필드의 최대 갯수 (기본 : 무제한)
const upload = multer({
	limit : {fileSize : 5,242,880} //5 * 1024 * 1024 (5MB)
});

fileFilter

파일의 유형을 필터링하는 속성이다. 함수 내에 file인자를 통해서 허용 시킬 파일을 필터링 할 수 있다. 아래 예제는 이미지 형식인 파일들만 허용하는 예제이다.

const upload = multer({
    fileFilter(req, file, done) {
        if (file.mimetype.lastIndexOf('image') > -1) {
            //파일 허용
            done(null, true);
        } else {
            //파일 거부
            done(null, false);
        }
    }
});

허용된 파일이 아니더라도 http 통신은 정상적으로 출력되기 때문에 명확한 오류를 표기하려면 직접 미들웨어 함수를 호출하면 된다.

const upload = multer({
    fileFilter(req, file, done) {
        if (file.mimetype.lastIndexOf('image') > -1) {
            //파일 허용
            done(null, true);
        } else {
            //파일 거부
            done(null, false);
        }
    }
}).single('file');

app.post('/photo', function (req, res, next) {
    upload(req, res, function error(error) {
        if (error) {
            res.status(500).send('허용된 파일이 아닙니다!');
            return;
        } else {
            res.status(200).send('upload success');
        }
    });
});

API

multer 사용 시 4개의 메서드를 제공하는데 각각의 역할은 다음과 같다.

  • single(filename) : 단일 파일에 대한 전달 요청 (위의 예제들)
  • array(fieldname, maxcount) : 동일한 필드에 대해 multiple속성이 적용된 파일들에 대한 전달 요청 (req.files에 배열 형태로 받을 수 있다.)
    <input type="file" name="file" id="uploadFile" multiple />
    
  • fields(fields) : 필드가 정의된 여러 파일을 전달 받는다. .array와 마찬가지로 req.files에 저장된다.
    <input type="file" name="main-image" id="uploadFile" /> <input type="file" name="sub-image" id="uploadFile" />
    

    fields를 사용할 때는 객체 배열로 받아와야한다.

    app.post('/photo', upload.fields([{name : 'main-image1'}, {name : 'main-image2'}), function(req, res){
        //code..
    });
    

참고 자료