Programming/javascrlpt

jQuery AJAX대신 XHR로 파일 다운로드하기

📝 작성 : 2022.08.23  ⏱ 수정 : 
반응형

Intro

a 링크를 통한 파일 다운로드를 제공 하고 있었는데, 개선이 필요했습니다.

전체 데이터를 poi를 활용해 엑셀 파일을 생성 한 뒤에 반출을 해 주는 과정인데, 데이터가 클 수록 파일을 작성하는데 워낙 시간이 오래 걸리다보니 기다리는동안 사용자 경험이 너무 좋지 않았습니다.

그래서 파일 다운로드 과정을 AJAX를 이용해 비동기로 요청하고, 요청을 기다리는 동안 waitMe 를 이용해 로딩바를 보여주는 식으로 개선을 하기로 했습니다.

gif

https://github.com/vadimsva/waitMe

AJAX

이를 위해 jQuery AJAX를 활용해 코드를 구현 해 보았습니다.

$('#export').on('click', function () {
    var wait = $(this);
    wait.waitMe();
    $.ajax({
        url: '/file/download/excel',
    }).done(function (data) {
        var blob = new Blob([data], { type: "application/octetstream" });
        var link=document.createElement('a');
        link.href=window.URL.createObjectURL(blob);
        link.download="projets.xlsx";
        link.click();
    }).always(function(){
        wait.waitMe('hide');
    });
})

이렇게 해서 테스트 했더니 blob 데이터로 a 링크를 만들어서 파일 다운로드도 까지 문제 없이 성공했습니다.

그런데.. 데이터가 다 손상이 되어버리는 문제가 발생했습니다.

AJAX 응답을 통해 받은 받은 응답을 확인해보니 typeOf(data)가 string으로 오고 있었는데, jQuery AJAX가 데이터를 먼저 처리 하면서 binary 데이터가 인코딩/디코딩 되는 과정에서 손상 된 것으로 보입니다.

XHR

다행히도 이때는, XMLHttpRequest를 바로 사용해서 해결이 가능했습니다.

아래의 링크에 따르면

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data

XMLHttpRequest 를 통해 Binary 데이터를 보내거나 받을 수 있다고 안내되어 있는데요.

이미지 파일을 다운 받는 예제 코드를 아래와 같이 작성 할 수 있습니다.

const req = new XMLHttpRequest();
req.open("GET", "/이미지파일주소.png", true);
req.responseType = "blob";

req.onload = (event) => {
  const blob = req.response;
  // blob 활용
};

oReq.send();

이를 토대로 아까의 코드를 XHR 을 사용하는 코드로 다시 작성 해 보았습니다.

$('#export_project').on('click', function () {
    var wait = $(this);
    wait.waitMe();
    const req = new XMLHttpRequest();
    req.open("GET", '/file/download/excel', true);
    req.responseType = "arraybuffer";
    req.onload = function() {
        const arrayBuffer = req.response;
        if (arrayBuffer) {
            var blob = new Blob([arrayBuffer], { type: "application/octetstream" });
            var link=document.createElement('a');
            link.href=window.URL.createObjectURL(blob);
            link.download="projets.xlsx";
            link.click();
            wait.waitMe('hide');
        }
    };
    req.send();
})

이렇게 코드를 작성하니 정상적으로 아래의 순서대로 진행이 되었고

  • 파일 다운로드 요청
  • 로딩 시작
  • 다운로드 완료
  • 로딩 종료

파일도 전혀 깨지지 않고 온전하게 다운로드 할 수 있었습니다.

XMLHttpRequest 호환성은 아래와 같습니다. 드디어 IE가 호환성 목록에서도 사라졌네요

image-20220823174132612

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

AJAX로 binary data를 다루는 방법에 대해 정말 많이 찾아보았는데도 애초에 그렇게 활용하는 사람들이 없는지 정말 많은 어려움을 겪었습니다.

혹시 꼭 AJAX를 써야겠다면 아래의 방법으로 할 수 있기는 한 듯 한데.. 확인해 보니 너무 복잡해서 XHR을 사용하는 편이 좋아 보입니다.

http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

이상입니다.

References

반응형