ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Node.js] multer를 이용한 파일 업로드
    programing/Language 2019. 1. 20. 19:39

    안녕하세요, Einere입니다.

    (ADblock을 꺼주시면 감사하겠습니다.)


    multer는 multipart/form-data를 다루기 위한 node.js 의 미들웨어 입니다.

    (multipart/form-data는 mime type중 하나입니다.)

    multer를 이용해서 서버에 파일을 업로드하는 방법을 알아보도록 하겠습니다.

    기본 환경은 express를 이용한 project입니다.



    multer 설치

    $ npm install --save multer

    express project 폴더 내부에서, 위의 명령어를 실행하여 multer를 설치합니다.




    file.js

    const express = require('express');
    const router = express.Router();
    const multer = require('multer');
    
    const storage = multer.diskStorage({
        destination(req, file, callback) {
            callback(null, 'uploads');
        },
        filename(req, file, callback) {
            let array = file.originalname.split('.');
            array[0] = array[0] + '_';
            array[1] = '.' + array[1];
            array.splice(1, 0, Date.now().toString());
            const result = array.join('');
            console.log(result);
            callback(null, result);
        }
    });
    
    const upload = multer({
        storage,
        limits: {
            files: 10,
            fileSize: 1024 * 1024 * 1024,
        }
    });
    
    router.post('/upload', upload.array('photo', 1), function (req, res, next) {
        try {
            const files = req.files;
            let originalName = '';
            let fileName = '';
            let mimeType = '';
            let size = 0;
    
            if (Array.isArray(files)) {
                console.log(`files is array~`);
    
                originalName = files[0].originalname;
                fileName = files[0].filename;
                mimeType = files[0].mimetype;
                size = files[0].size;
                
            } else {
                console.log(`files is not array~`);
                originalName = files[0].originalname;
                fileName = files[0].filename;
                mimeType = files[0].mimetype;
                size = files[0].size;
            }
    
            console.log(`file inform : ${originalName}, ${fileName}, ${mimeType}, ${size}`);
    
            res.writeHead('200', {
                'Content-type': 'text/html;charset=utf8'
            });
            res.write('<h3>upload success</h3>');
            res.write(`<p>original name = ${originalName}, saved name = ${fileName}<p>`);
            res.write(`<p>mime type : ${mimeType}<p>`);
            res.write(`<p>file size : ${size}<p>`);
            res.end();
        } catch (err) {
            console.dir(err.stack);
        }
    });
    
    module.exports = router;

    express project의 routes폴더에 "file.js"로, 라우팅 파일을 만듭니다.


    우선, multer.diskStorage()를 이용해 파일 저정 관련 옵션을 설정합니다.

    destination()은 express project에 "uploads"라는 폴더를 지정합니다. 만약, 다른 폴더로 수정하고 싶으시다면, callback()의 2번째 인자인 "uploads"를 원하는 폴더명으로 수정하시면 됩니다.

    filename()은 저장할 파일명을 수정할 수 있게 해주는 함수입니다. 저는 간단하게 "기존파일명_저장시점.확장자"의 형식으로 저장되도록 함수를 구현하였습니다.


    그리고 다시 multer를 이용해 아까 설정한 storage와 함께, 리미트를 걸어줍니다. 한번에 업로드하는 파일의 개수는 최대 10개, 크기는 1MB로 설정했습니다.


    multer에 대한 설정이 끝났으니, router를 이용하여 라우팅을 합니다. multer는 form태그를 이용한 post방식에 대해서만 유효하므로, post()를 이용해 라우팅합니다.

    router()의 두번째 인자에 upload.array('photo', 1)을 넣어주어, 업로드된 파일의 필드명중 'photo'를 가져오며, 업로드한 파일중 가져올 파일의 개수를 1개로 설정합니다.

    나머지 부분은 업로드한 파일의 정보를 얻어서, response로 보내주는 코드입니다.




    upload.html 작성

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>photo upload</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
        <h1>file upload</h1>
        <form method="POST" enctype="multipart/form-data" action="/files/upload">
            <table>
                <tr>
                    <td><label>file</label></td>
                    <td><input type="file" name="photo"></td>
                </tr>
            </table>
            <input type="submit" value="upload" name="submit">
        </form>
    </body>
    </html>

    해당 파일은 app.js에서 public으로 공개한 폴더 내부에 작성하시면 됩니다. 저같은 경우에는 "public/upload.html"입니다.


    단순히 form태그를 이용하여, mime type은 multipart/form-data, post방식으로 전송합니다.

    전송 할 목적지는 "/files/upload"입니다.


    input태그의 name속성으로 지정한 값은, multer에서 fieldname에 저장되는 값입니다.

    즉, 예제의 경우 name속성이 "photo"이므로, multer에서 upload.array('photo', 1)이 되는 것입니다.




    app.js 수정

    var createError = require('http-errors');
    var express = require('express');
    var path = require('path');
    const expressSession = require('express-session');
    var cookieParser = require('cookie-parser');
    var logger = require('morgan');
    
    const fileRouter = require('./routes/file');
    
    var app = express();
    
    // view engine setup
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'jade');
    
    app.use(logger('dev'));
    app.use(express.json());
    app.use(express.urlencoded({
        extended: false
    }));
    app.use(cookieParser());
    app.use(expressSession({
        httpOnly: true, //only https
        secure: true,
        secret: 'my key', //encryption key
        resave: false,
        saveUninitialized: true,
        // store: new fileStore(), //save session to file
    }));
    app.use(express.static(path.join(__dirname, 'public')));
    app.use(express.static(path.join(__dirname, 'uploads')));
    
    // route
    app.use('/files', fileRouter);
    
    // catch 404 and forward to error handler
    app.use(function (req, res, next) {
        next(createError(404));
    });
    
    // error handler
    app.use(function (err, req, res, next) {
        // set locals, only providing error in development
        res.locals.message = err.message;
        res.locals.error = req.app.get('env') === 'development' ? err : {};
    
        // render the error page
        res.status(err.status || 500);
        res.render('error');
    });
    
    module.exports = app;

    file.js를 라우팅해야 하니, require()로 import합니다.


    그리고 서버가 public으로 공개해야 할 디렉토리에 "uploads"폴더를 추가합니다.

    해당 폴더는 multer를 이용해 서버에 업로드한 파일이 저장되는 폴더입니다. 물론, 실제로 폴더를 생성하는것도 잊으면 안됩니다.


    그리고 저는 "/files"로 라우팅하였습니다.


    이제 $ npm start를 입력하여 서버를 구동합니다.




    테스트


    우선, "localhost:3000/photo.html"로 접속하여, 파일 전송 페이지로 이동합니다.


    그리고 파일 선택으로 업로드할 파일을 선택한 뒤, upload 버튼을 누릅니다.




    그러면 위와 같이 "localhost:3000/files/upload"로 이동하게 되어, 결과 화면이 뜹니다.



    더 자세한 내용은 하단의 링크를 참고해주세요. 한글로 되어 있어 읽기 편합니다.




    참고 : multer readme

    댓글

Designed by black7375.