KDT 코딩온 개발 14기 수강일기

KDT 포스코X코딩온 웹 과정 14기 21일 - node js의 파일 업로드

worldstroy 2024. 11. 30. 12:58

[ 목차 ]

     

    1. 파일 업로드 프론트 엔드에서의 작업

    <form action = "/upload" method = "POST" enctype "multipart/form-data">
    <input type = 'file' name = 'userfile'/> <br/>
    <input type = "text" name = "title" /> <br/> <br/>
    <button type = "submit"> 업로드 </button>
    </form>

     

    1)  form 테그의 enctype 속성으로 "multipart/form-data"를 반드시 설정한다.

                                   - multer 미들웨어의 경우 "multipart/form-data"가 아닌 폼에서는 동작하지 않음.

     

    2. node js 서버에서의 작업 = multer

    설치 명령어 : npm install multer

     

    - 파일 업로드를 위해 사용되는 미들웨어로 주로 express를 통해 서버를 구축할 때 많이 사용됨.

     

    1) 파일 업로드 경로 설정 

    const multer = require('multer');
    const upload = multer({
        dest : 'uploads/',
    });

     

    dest 속성 : 파일을 업로드하고 그 파일이 저장될 경로를 지정하는 속성

     

    2) 하나의 파일을 업로드 할 때? 

     

    #. 프론트엔드

      <form action="/upload" method="post" enctype="multipart/form-data">
          <input type="file" name="userfile" />
          <input type="text" name="title" /> <br /><br />
          <button>업로드</button>
        </form>

     

    #. 백엔드

    //multer 관련 설정
    const multer = require("multer");
    const path = require("path"); // 경로 처리를 위한 내장 모듈
    
    const upload = multer({
      dest: "uploads/", // dest : 클라이언트가 업로드한 파일을 저장할 서버측 검토
    });
    
    app.post("/paractice-POST", upload.single("userfile"), (req, res) => {
      console.log(req.file);
      res.render("paractice-POST", {
        title: "아이디 정보",
        userInfo: req.body,
        file: req.file, //파일 정보도 넘겨 줘야 함.
      });
    });

     

    req. file에 대한 정보가 없을 때엔 에러를 발생 시키기에 따로 상황에 따른 router를 따로 두어야 한다.

     

    3) multer - 하나의 요청 안에 여러 개의 파일이 존재할 때

     

     

    (프론트 엔드)

    <h2>Multiple file upload v1</h2>
        <p>하나의 인풋에 여러개의 파일을 업로드</p>
        <form action="/upload/array" method="post" enctype="multipart/form-data">
          <input type="file" name="userfiles" multiple />
          타이틀 <input type="text" name="title" /> <br /><br />
          <button>업로드</button>
        </form>

     - 간단하게 file 테그에 multiple 속성을 추가 시켜주면 된다. 

     

    (서버 단에서 할 일)

    // 2. array() : 여러 파일을 한번에 업로드
    //uploadDetall.array("userfiles");
    //파일을 업로드 한 후, req.files라는 객체가 생성됨.
    app.post("/upload/array", uploadDetail.array("userfiles"), (req, res) => {
      console.log(req.files); // [{파일1의 정보}, {파일2의 정보}, {파일3의 정보}, ....]
      console.log(req.body); //
      res.send("하나의 인풋에 여러 파일 업로드 완료");
    });

    - 하나의 파일 만 업로드하는 기능인 경우와 달리, req.files에 배열의 형태로 객체로 정보가 담기는 것을 확인할 수 있다.

     

    4) 여러개의 파일을 여러개의 요청으로 보내고 싶을 때

     

    (프론트엔드 단에서 해줘야 할 일)

        <h2>Multiple file upload v2</h2>
        <p>여러개의 인풋에 각각의 파일을 업로드</p>
        <form action="/upload/fields" method="post" enctype="multipart/form-data">
          <input type="file" name="userfile1" />
          <input type="file" name="userfile2" />
          타이틀 <input type="text" name="title" /> <br /><br />
          <button>업로드</button>
        </form>

     

    - 인풋 테그의 갯수 만큼 파일을 저장하여 처리하는 방식이라고 생각하면 된다.

     

    (백엔드)

    app.post(
      "/upload/fields",
      uploadDetail.fields([{ name: "userfile1" }, { name: "userfile2" }]),
      (req, res) => {
        console.log(req.files);
        console.log(req.body);
        res.send("여러 인풋에 각각의 파일 업로드 완료");
      }
    );

     

    - fields에 들어간 배열 내의 객체 숫자 만큼, input 테그로 받은 파일을 업로드할 수 있다. 

     

    5) axios를 사용한 동적 파일 업로드 

     

    (프론트 엔드)

        <h2>동적 파일 업로드</h2>
        <input type="file" name="dynamicUserFile" id="dynamic-file" />
        <br />
        <button onclick="fileUpload()">업로드</button>
        <br />
        <!-- 업로드한 이미지를 보여줄 img 테그 요소 -->
        <img src="" alt="" />
        <script>
          function fileUpload() {
            //동적 파일 업로드
            // js 만으로 폼을 전송
            // 파일 데이터를 전송할 떄 FormData 객체를 활용할 것임.
            //FormData란?
            // form 테그의 데이터를 동적으로 제어할 수 있는 기능
            const formData = new FormData();
            const file = document.querySelector("#dynamic-file");
            console.log(file);
            console.log(file.files);
            formData.append("dynamicUserFile", file.files[0]);
            axios({
              method: "post",
              url: "dynamicFile",
              data: formData,
              headers: {
                "Content-Type": "multipart/form-data",
              },
            }).then((res) => {
              const { data } = res;
              console.log(data);
    
              const img = document.querySelector("img");
              img.src = "/" + data.path;
            });
          }
        </script>

     

    -  1. formdata 객체에 input 테그를 통해 받은 정보를 append 한다.
    -  2. axios 요청을 보낼 때 header 변수를 통하여, 해당 파일이 multipart/form-data" 타입임을 명시한다.
    -  3.  서버에 요청을 보낸 뒤 다시 .then 이나 async - await 방식을 통해 정보를 받은 이후 추가 처리를 하면 된다.

     

    (백엔드)

    app.post("/dynamicFile", uploadDetail.single("dynamicUserFile"), (req, res) => {
      console.log(req.file);
      res.send(req.file);
    });

     

    서버 단에서 해줘야 할 역할은 앞선 3가지 방식과  크게 다르지 않다.

    3.  multer의 세부 설정

     

     

    #. 경로 뿐 아니라 파일명, 파일 크기 등을 직접 지정, 제어할 수 있다.

    const uploadDetailpar = multer({
      storage: multer.diskStorage({
        //destination : 경로 설정
        destination(req, file, done) {
          // done : callback function
          // done(null, "~~~") 여기서 null은 error를 의미하는 매개 변수
          // 에러가 없으므로 "null" 이라고 전달하여 콜백함수를 호출
          done(null, "uploads/");
        },
        filename(req, file, done) {
          const ext = path.extname(file.originalname); // 파일 "확장자를 추출"
          console.log("ext  :", ext);
          console.log(path.basename(file.originalname, ext));
          done(null, path.basename(file.originalname, ext) + req.body.id + ext);
        },
      }),
      limits: { fileSize: 5 * 1024 * 1024 },
    });

     

    storge : 저장한 공간에 대한 정보
    diskStorage : 파일을 디스크에 저장하기 위한 모든 제어 기능을 제공
    destination : 저장할 경로
    filename : dest 속성을 통해 설정한 폴터에 넣을 파일의 이름.

     

     

    4. multer를 간단하게 정리해보면 ...

    • single() : 하나의 파일 업로드
          • req.file : 파일 하나
          • req.body : 나머지 정보
    • array() : 여러 파일을 업로드할 때 사용, 하나의 요청 안에 여러 개의 파일이 존재할 때
          • req.files : 파일 n개
          • req.body : 나머지 정보
    • fields() : 여러 파일을 업로드할 때 사용, 하나의 요청이 아닌 여러 개의 요청이 들어올 때
         • req.files : 파일 n개
         • req.body : 나머지 정보

     

     

     

    참고 자료

    - 코딩온 부트 캠프 ppt 자료