ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • multer - 파일 업로드
    JavaScript/Node.js 2018. 11. 26. 15:27

    multer - 파일 업로드

    Express에서 파일 업로드를 수행 및 처리하기 위해서는 외부 패키지를 설치해야한다.

    스프링에서 파일 업로드를 처리하기 위해서 commons-io, commons-fileupload같은 라이브러리를 사용하듯 Express에서도 외부 패키지를 설치해야 파일 업로드를 정확히 말하면 multipart/form-data를 처리할 수 있게된다.




     multer

    npm사이트에서 multer 패키지를 검색해보자.

    "Multer는 파일 업로드를 위해 사용되는 multipart/form-data 를 다루기 위한 node.js 의 미들웨어입니다. 

    효율성을 최대화하기 위해 busboy를 기반으로 하고 있습니다."

    라고 설명되어 있고 한국어 번역을 지원한다.




     설치방법

    설치 방법은 아래와 같다.


    cmd에서 해당 구분을 통해 multer를 설치하자.




     사용법

    사용법을 보고 사용방법을 터득해보자.

    1. "require('multer')"를 통해 multer모듈을 포함시킨다.

    2. multipart/form-data는 POST로 데이터를 전달하기 때문에 반드시 라우트는 post()를 사용한다.

    3. 파일 단일 객체인 경우 처리를 single()을, 다중 객체인 경우 array()를 사용한다. 

    4. 만약 파일을 하나의 name으로 묶지 않으되 여러개의 파일을 업로드하는 경우 fields()를 사용한다.


    그럼 이제 single()기능과 array(), fields()기능을 자세히 알아보자.


    단일 파일 업로드 기능을 처리하기 위해서는 single()함수를 사용하고 다중 파일 업로드 기능을 처리하기 위해서는 array()함수나 fields()함수를 사용한다.


    array()와 fields()의 차이는 다음과 같다.

    HTML 파일 태그를 사용할 때, 아래의 두가지 타입으로 사용할 수가 있다.

    1
    2
    3
    4
    // 하나의 name으로 묶어서 다중 파일을 하나의 객체로 사용하는 경우 
    <input type="file" name="user_files">
    <input type="file" name="user_files">
    <input type="file" name="user_files">
    cs
    1
    2
    3
    4
    // 각각의 name으로 다중 파일을  객체로 사용하는 경우
    <input type="file" name="user_profile_file">
    <input type="file" name="user_title_file">
    <input type="file" name="user_content_file">
    cs

    1. 하나의 name으로 묶어서 다중 파일을 하나의 객체로 사용하는 경우

    이는 하나의 객체안에 배열로 파일 정보들을 서버로 전달하게 된다.

    EX)

    [file_info0, file_info1, file_info2]

    이런 형식으로 말이다.

    그러니 개별 파일 정보에 접근하기 위해서는 "req.file[index]" 이런식으로 접근을 하게 된다.


    2. 각각의 name으로 다중 파일을 객체로 사용하는 경우

    이는 하나의 배열안에 객체별이나 배열로 파일 정보들을 서버로 전달하게 된다.

    EX)

    [

        { user_profile_file },

        { user_title_file },

        { user_content_file }

    ]

    또는

    [

        { user_profile_file[file_info0, file_info1, ...] },

        { user_title_file[file_info0, file_info1, ...] },

        { user_content_file[file_info0, file_info1, ...] }

    ]

    이런 형식으로 서버에 전달한다.

    각각의 파일에 접근하기 위해서는 "req.file['HTML_file_tag_name']" 또는 "req.file['HTML_file_tag_name'][index]" 이런식으로 접근을 하게 된다.



    각 함수들의 사용방법을 알아봤으니 이제 파일 업로드를 할 때 파일을 위치시키기 위한 디렉토리 지정방법을 알아보자.

    Multer 객체는 몇가지의 옵션을 제공한다.

    그 중 가장 중요한 파일 저장 위치에 대해서 알아보자.


    설명하고 있듯이 보통의 웹 앱에서는 dest옵션으로도 충분히 파일 저장 위치를 지정하는 것에 문제가 없다고 한다.

    그것보다 더 업로드를 제어하고 싶다면 storage옵션을 통해 상세한 처리가 가능하다고 설명하고 있다.

    DiskStorage()와 MemoryStorage()를 사용하는 방법과 설명 또한 상세하게 나와있으니 이를 참고해서 작업하도록 하자.




     컨셉잡기

    multer를 이용해서 파일 업로드를 구현할 수 있다는 것을 알았다.

    이제 이를 활용해서 어떻게 파일 업로드를 할 것인지 컨셉을 가져보자.


    1. 사용자가 "/upload" URL로 들어오면 파일을 등록시켜주는 폼을 표현해준다.

    2. 파일 선택을 눌러 업로드할 대상을 지정하고 전송버튼을 클릭하면 app_file.js 웹 애플리케이션 서버에 파일 정보를 전달한다.

    3. 파일 정보를 전달받은 서버에서 파일을 처리하고 처리 결과를 사용자에게 알려준다.




     구현하기

    컨셉을 잡았으니 이제 구현을 통해 서비스를 제공해보자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    /** require() 영역 */
    const express = require('express');
    const bodyParser = require('body-parser');
    const fs = require('fs');
    const multer = require('multer');
    // 파일 저장 위치를 dest옵션으로 지정할 경우
    var upload = multer({ dest: 'uploads/' });
     
    // 파일 저장 위치를 diskStroage()함수로 지정할 경우
    var storage = multer.diskStorage({
        destination: (req, file, cb) => {
            cb(null'uploads/');
        },
        filename: (req, file, cb) => {
            cb(nullDate.now() + '-' + file.originalname);
        }
    });
    var upload = multer({ storage: storage });
    cs

    5번 줄 - 

    가장 먼저 중요한 multer를 애플리케이션에 불러온다.


    6번 줄 - 

    만약 multer()의 dest옵션을 사용하여 파일 저장 위치를 지정할 경우 위와 같이 사용하면 된다.


    10 ~ 18번 줄 - 

    만약 multer()의 storage옵션을 사용하여 파일 저장 위치를 컨트롤 할 경우 위와 같이 사용하면 된다.


    이제 라우트를 작성하자.

    1
    2
    3
    4
    // 파일 업로드 폼 페이지 이동
    app.get('/upload', (req, res) => {
        res.render('uploadform');
    });
    cs

    2 ~ 4번 줄 - 

    "/upload"로 사용자가 요청을 할 경우 'uploadform' 템플릿으로 이동시켜준다.



    uploadform.pug를 생성하고 템플릿을 작성하자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    doctype html
    html
        head
            meta(charset="utf-8")
            title uploadForm
        body
            form(action="/upload" method="POST" enctype="multipart/form-data")
                input(type="file"name="userfile")
                input(type="submit", value="전송")
    cs

    7번 줄 - 

    /upload를 action으로 지정하고 POST메소드로 데이터를 전송한다.

    가장 중요한건 enctype이다.

    파일 업로드를 수행하기 위해서는 enctype이 반드시 multipart/form-data로 지정해줘야 서버에서 multer를 활용해 파일 데이터를 처리할 수가 있다.


    8번 줄 -

    한가지 잊지 말아야할 것은 file태그의 name을 설정해야한다는 것이다.

    템플릿에서 file태그의 name을 설정하고 이 name값을 multer의 single()이나 array()함수의 인자로 지정해줘야 파일 처리가 가능하다.



    템플릿에서 form태그로 전달되는 파일 데이터를 처리하기위한 post()라우트를 작성하자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 파일 업로드 처리
    app.post('/upload', upload.single('userfile') , (req, res) => {
        /*
            upload.single('html 파일태그의 name')은 콜백함수보다 먼저 수행됨.
            사용자가 전송한 데이터에 파일이 포함된 경우 그것을 가공해서 request객체에 file이라는 속성을 추가한다.
        */
        console.log(req.file);
        res.send('uploaded: ' + req.file.filename);
    });
    cs

    2번 줄 - 

    single() 혹은 array()의 인자로 들어가는 String은 반드시 템플릿에서 작성한 file태그의 name과 동일해야한다.

    multer의 single()이나 array()함수내부에서 file태그의 name정보를 이용해 핸들링 할 파일 객체 정보를 request에 추가한다.


    7번 줄 - 

    사용자가 파일을 업로드할 경우 터미널 혹은 cmd에 파일 정보를 로그로 출력한다.




     실행

    컨셉대로 기능을 만들었으니 이제 직접 테스트해보자.


    localhost:9100/upload로 접속하면 아래와 같이 파일 선택 폼이 나타난다.

    파일을 선택하고 전송버튼을 클릭하면 전송된 파일 정보를 화면에 출력해준다.

    uploads폴더를 확인해보면 실제로 파일이 업로드된 것을 알 수가 있다.

    파일이 업로드되면 콘솔화면에 업로드 한 파일의 정보를 출력해준다.


Designed by Tistory.