본문 바로가기

TIL

2021.04.13(node js formdata file upload)

app.use(express.json())
app.use(express.urlencoded({extended:false}))

먼저 formdata를 사용하기 위해서는 body-parser을 설정해줘야한다. 

 

const multer = require("multer");

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "./uploads/");
  },
  filename: function (req, file, cb) {
    cb(null, new Date().toISOString() + file.originalname);
  },
});

multer 모듈을 사용하여 post로 전송된 파일처리를 해준다. 

dest대신 storage 속성을 이용해 upload를 진행하면 destination, filename을 조작하는 것을 볼 수 있다. 

 

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

router.patch(
  "/",
  authMiddleware,
  upload.single("profileImage"),
  async (req, res) => {

    const result = { status: "success" };

    res.json(result);
  }
);

multer을 사용한 것은 upload.single()을 통해 해당 데이터를 불러올 수 있다. upload.single()안에 들어가야할 함수는 filename임으로 front에서 file name속성을 가지고 오면 된다. 

          <form id="form" method="patch" >

          <div class="file is-boxed">
            <label class="file-label">
              <input
                class="file-input"
                type="file"
                name="profileImage"
                id="profileImage"
                accept="image/*"
              />
              <span class="file-cta">
                <span class="file-icon">
                  <i class="fas fa-upload"></i>
                </span>
                <span class="file-label"> Profile image Upload </span>
              </span>
            </label>
          </div>
  
          <button
            type="submit"
            class="button is-large is-fullwidth"
            onclick="nicknameUpload()"
          >
            Upload
          </button>

        </form>

form태그안에 type이 file에서 name의 속성을 가지고 와 upload.single() 넣으라는 의미이다. 

 

app.use('/uploads',express.static('uploads'))

우선 express.static의 정의는 직접 값에 변화를 주지 않는 이상 변하지 않는 파일을 의미하는 것이고 express 변수에는 static이라는 method가 포함되어 있어서 이 method로 middleware을 load해준다. 

 

        let formData = new FormData();
        formData.append('nickname',$('#nickname').val())
        formData.append('profileImage', $("#profileImage")[0].files[0], $("#profileImage")[0].files[0].name)

button을 눌렀을 때 form태그 안에 있는 전달하고자하는 data를 jquery로 가지고와서 formData.append()안에 작성할 때 왼쪽은 key, 오른쪽은 value를 작성하면 된다. 그런데 파일로드를 통한 이미지일 경우에는 key, value, value.name을 가지고 오면 된다. 

 

        $.ajax({
          cache:false,
          processData:false,
          contentType:false,
          type: "PATCH",
          url: `/profile`,
          enctype: 'multipart/form-data',
          headers: {
            authorization: `Bearer ${localStorage.getItem("token")}`,
          },
          data: formData,
          success: function (response) {
            if (response["result"] == "success") {
              window.location.href = "/board";
            }
          }
        });

ajax 부분을 보면 data를 한번에 formData로 보내는 것을 볼 수 있다. 나도 그 부분에 있어서 나눠서 보낼려고 시도를 했지만 form태그 안에 있는 data를 보낼 때는 한번에 묶어서 보내야하는 것을 알게 되었다. 

headers 안에 authorization은 token을 보낼 것이기 때문에 넣었고 여기서 추가적으로 진행된 부분은 cache, processData, contentType, enctype에 대한 설정이다. 사실 이부분은 이해하고 넣었다기 보다는 데이터를 보낼 때 기본적으로 넣은 것으로 보고 진행을 했기 때문에 추후에 다시 공부할 예정이다. 

 

이렇게해서 데이터를 전송하면 fiddler을 통해서 

제대로 이미지랑 nickname이 전달되는 것을 확인했고 postman에서도 

제대로 서버에 보내져서 status에서 success하는 것도 확인을 할 수 있었다. 

 


반성할 부분

 

내가 주로 작업을 했을 때 input에서 글을 작성한 것을 jquery로 가져와서 보내는 것은 자주해봤지만 file을 form태그를 이용해서 하는 것을 알지 못했다. html의 기초인데 그 기초를 놓치고 여기에 하루를 투자해도 진전이 있지 않았다. 

물론 여러번 만드는 것도 중요하지만 다시 한번 javascript의 기초를 제대로 이해하면서 다시 임한다면 스스로 풀 수 있는 능력을 기를 수 있을 것이다. 새롭게 접근했다기보다는 기본을 잊으면 발전할 수 없다는 것만 알게 되었다.