티스토리 뷰

반응형

파일 다운로드 기능을 구현하면서 약간의 삽질을 하면서 애를 먹었는데 덕분에 새로운 사실들을 알게 되었다.

  1. 서버에서 ByteArray 값을 내려주는 경우 파일로 만들어 내려받기
  2. 서버에서 response header에 보내주는 Content-Disposition 정보 사용하기

검색으로 여러가지 자료를 봤었는데 가장 도움이 되었던 건 아래 링크!

http://1004lucifer.blogspot.com/2019/04/axios-file-download-with-vuejs.html

 

[Axios] File Download 방법 (with Vue.js)

서버에서 ByteArray 형식으로 파일을 내려주는 상황에서 아래와 같은 로직으로 파일 다운로드 처리를 했다. 서버에서 헤더의 Content-Disposition 정보에 파일명을 내려줘야 한다. ================== 201...

1004lucifer.blogspot.com

먼저 ByteArray로 내려주는 값을 받기 위해서는 axios 헤더에 responseType을 추가해야 한다.

async fileDownload() {
  const url = '/download/file';
  const res = await axios.get(url, {
  	headers: { responseType: 'arraybuffer' }
  });
}

실제 코드는 axios interceptors를 사용하고 있고 api로직을 service로 분리해놓아서 좀 다르지만 간단하게 표현하면 위와 같다.

 

axios로 응답을 받으면 다음과 같이 <a> 태그를 만들고 해당 객체를 URL로 만들어서 클릭하고 다운받도록 구성한다.

const url = window.URL.createObjectURL(new Blob([res.data]));
const link = document.createElement('a');
const contentDisposition = res.headers['content-disposition']; // 파일 이름
let fileName = 'unknown';
if (contentDisposition) {
  const [ fileNameMatch ] = contentDisposition.split(';').filter(str => str.includes('filename'));
  if (fileNameMatch)
  	[ , fileName ] = fileNameMatch.split('=');
}
link.href = url;
link.setAttribute('download', `${fileName}`);
link.style.cssText = 'display:none';
document.body.appendChild(link);
link.click();
link.remove();

여기에서 중요한 점이 response 안에 content-disposition이란 값에 파일 이름이 같이 내려온다.

이게 브라우저 네트워크 탭에서 보면 분명히 보이는데 axios Response 객체에는 아무리 찾아도 없다. 이것때문에 멘붕해서 여기저기 질문하고 검색했는데 결론은 CORS 이슈였다!

 

여기 스택오버플로우에 보면 브라우저가 접근 가능한 헤더는 디폴트 값이 아래와 같다.

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

그래서 그 외 다른 값을 읽으려면 서버에서 특정 헤더 접근을 허용하는 exposedHeaders 와 같은 작업을 해줘야 한다.

그러고 나면 위 코드처럼 res.headers로 접근 가능하며 파일 이름을 가져올 수 있다.

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함