1. 먼저 axios로 파일 다운로드를 요청할 때, responseType을 arraybuffer로 지정해준다.
const excelDownload = () =>
  axios({
    headers: {
      //
    },
    responseType: 'arraybuffer',
    url: `${process.env.REACT_APP_API_URL}`,
    params: {
      //
    },
  });

2. request를 받아 Blob 객체를 만든다.

이때 백에서 heades에 content-type과 encoded-disposition에 파일의 정보를 담아 보내주어야 한다.

content-type을 Blob 객체를 선언할 때 type을 정의하는데 만약 항상 고정되어 있는 타입을 받아온다면 하드코딩으로 해도 된다.

encoded-disposition은 파일의 이름을 지정할 때 쓰인다. 경우에 따라 디코딩을 해야한다(예시에 방법기재)

const downloadFile = (file) => {
  let blob = new Blob([file.data], {
    type: file.headers['content-type'],
  });
  let name= decodeURIComponent(file.headers['encoded-disposition']); //파일명 디코딩
  fileName = getFileName(name);
  if (window.navigator.msSaveOrOpenBlob) { // IE 10+는 해당 함수 제공
    window.navigator.msSaveOrOpenBlob(blob, name);
  } else {
    let link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.target = '_self';
    if (name) link.download = name;
    link.click();
    window.URL.revokeObjectURL(link); //메모리 누수 방지
  }
};


export const getFileName = (contentDisposition) => {
    let fileName = contentDisposition
      .split(';')
      .filter((el) => el.indexOf('filename') > -1)
      .map((ele) => ele.replace(/"/g, '').split('=')[1]);
    return fileName[0];

};

주의할 점 : GC가 작동하지 않기 때문에 revokeObjectURL로 메모리 누수를 방지해야한다!

Leave a comment

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다