#JavaScript XMLHttpRequest 파일 업로드하기

2020. 1. 12. 21:41 개발 이야기/JavaScript

 

 

jquery XMLHttpRequest를 이용해서

 

GET, POST 전송

 

파일 업로드까지 알아보도록 하겠습니다.

 

 

먼저 GET 전송하기!

 

$('#btn_export').click(function () {
            const tag_no = $('#tag_selector2').val();
            const r = new XMLHttpRequest();
            r.open('GET', '/target/exportTarget?tag_no=' + tag_no, true);
            r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            let fileName = null; //if you have the fileName header available
            r.withCredentials = true;
            r.responseType = "blob";
            r.onreadystatechange = function () {
                if (r.readyState === 4) {
                    if (r.status === 200) {
                        const blob = r.response;
                        if (r.getResponseHeader("content-disposition")) {
                            var contentDisposition = r.getResponseHeader("content-disposition");
                            fileName = contentDisposition.substring(contentDisposition.indexOf("=") + 1);
                        } else {
                            fileName = "unnamed.xlsx";
                        }

                        console.log(fileName);
                        const link = document.createElement('a');
                        link.href = window.URL.createObjectURL(blob);
                        link.download = fileName;
                        link.click();
                    }
                }
            };
            r.send();

        });

 

id = btn_export 버튼을 누르게되면

 

tag_selector2의 값을 가져와서

'/target/exportTarget?tag_no=' + tag_no

 

요렇게 값을 넣어 전송하게됩니다.

 

제가 구현한 로직은 generate한 excel 파일을 가져오는 function인데요!

 

간단히 설명을 하자면

 

r.withCredentials = true;
r.responseType = "blob";

 

저는 JWToken을 사용하는데요

 

cookie에 있는 정보를 붙여서 request 날리고자 할때는 꼭!

 

withCredentials를 true로 넣어주셔야 토큰을 장착한 후 전송하게 됩니다

 

그리고 responseType blob으로 넣은 것은

 

응답에 파일이 첨부되어 날라오는데 이를 가져오기 위함입니다!

const blob = r.response;
if (r.getResponseHeader("content-disposition")) {
    var contentDisposition = r.getResponseHeader("content-disposition");
    fileName = contentDisposition.substring(contentDisposition.indexOf("=") + 1);
} else {
    fileName = "unnamed.xlsx";
}

console.log(fileName);
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();

response 값을 blob으로 넣고

 

URL을 만든 후 link를 만들어 클릭까지 구현해줘야 자동으로 내가 다운로드를 눌렀구나!

 

생각하도록 아래와 같은 창이 뜨게됩니다!

 

 

여기서 key point는 

 

백엔드에서 파일을 보내줄 때

r.getResponseHeader("content-disposition");

 

이 속성을 꼭 넣어주어야하는데요

 

이 속성을 빠뜨리면 파일 명을 가져올수 없게 되니까 꼭 신경써주세요

 

다음은 POST를 구현해보겠습니다

 

GET과 다른점이 있다면 파라미터인데요

 

GET 방식은 url.com?param=123

 

이런식으로 나라가게 된다면

 

POST 방식은 url.com

 

이렇게 날아가고 파라미터를 같이 전송하게 됩니다.

 

        $('#target_reg').click(function () {
            const tg_email = $('#target_email').val();
            const tg_name = $('#target_name').val();
            const formData = {
                tg_email: tg_email,
                tg_name: tg_name,
            };
            // console.log(formData);

            const r = new XMLHttpRequest();
            r.open('POST', '/target/regTarget', true);
            r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            r.withCredentials = true;
            r.onreadystatechange = function () {
                let rObj;
                if (r.readyState === 4) {
                    if (r.status === 200) {
                        document.location.reload();
                    } else {
                        rObj = JSON.parse(r.responseText);
                        alert(rObj.err);
                    }
                }
            };
            r.send(JSON.stringify(formData));
        });

저는 formData를 만들어주고

 

이른 JSON으로 변환해서 보냈습니다

r.open 부분에 POST를 넣어주고 

r.send()에 값을 넣어 전송하면 끝입니다.

 

 

마지막으로 파일 업로드를 구현해보도록 하겠습니다.

 

<div class="form-group">
     <div class="form-file">
         <button class="btn-file"><i class="la la-upload"></i></button>
         <input type="file" id="file" name="file">
         <div class="file-container">
            <p id="uploadFileName">test.xlsx</p>
            <progress value="22" max="100"></progress>
        </div>
    </div>
</div>

먼저 file type의 input 태그를 만들어주고

클릭을 해보겠습니다.

 

 

이렇게 창이 열리면서 file을 업로드할 수 있는 창이 뜨게됩니다.

 

여기서 파일을 골라 열기를 누르면 브라우저에 임시 저장이 되는것 같습니다.

 

이상태로 서버로 전송을 하려면!

$('#excelUpload-btn').click(function () {
                var data = new FormData();
                data.append("file", $('#file').prop('files')[0]);
                console.log(data);
                $.ajax({
                    type: "POST",
                    enctype: 'multipart/form-data',
                    url: "/target/importTargets",
                    data: data,
                    processData: false,
                    contentType: false,
                    cache: false,
                    timeout: 600000,
                    xhrFields: {
                        withCredentials: true
                    },
                    success: function (result) {
                        console.log("SUCCESS : ", result.data);
                        alert('전송이 완료되었습니다.');
                        location.reload();
                    },
                    error: function (e) {
                        console.log("ERROR : ", e);
                    }
                });
           
        });

id = file의 files 어레이의 0번 파일을 가져와

 

data에 append 시킵니다

 

아 여기서는 갑자기 ajax를 썻네요 ㅎㅎ;

 

중요한 점은

enctype: 'multipart/form-data',

data: data,

이부분을 넣어야 request에 파일이 날아가게 됩니다.

 

백엔드에서 확인을 하게되면

 

 

 

 

 

정상적으로 파일이 날라와 파일명이 로그에 찍히는 것을 볼 수있습니다.

 

이상입니다.