- 먼저 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로 메모리 누수를 방지해야한다!