본문 바로가기
frontend

JS로 파일 다운로드

by marble25 2023. 9. 10.

업무를 하다 보니 MinIO라는 blob storage에서 파일을 다운로드해야하는 경우가 생겼다.

버튼을 클릭하면 Storage에 url을 요청해서 다운로드하는 것을 구현해야 했다. 즉, js로 동적으로 다운로드를 구현해야 하는 것이다.

다운로드를 구현하는 방법에는 크게 2가지가 있다.

  1. blob 객체 먼저 다운로드 → 해당 blob 객체를 사용할 수 있는 url을 클릭
async function download(url: string, filename: string) {
  const link = document.createElement("a");
  const resp = await fetch(url);
  const blob = await resp.blob();
  link.href = URL.createObjectURL(blob);
  link.download = filename;
  link.click();
}

1차적으로 url에서 blob 객체를 fetch해 온다.

그 후, 해당 blob을 url로 다시 만들고, a 태그로 wrap해서 가상으로 click한다.

  • 장점
    • 다운로드 progress를 ui로 보여주는 등의 더 다양한 동작을 구현할 수 있다.
    • filename을 다시 지어줄 수 있다.
  • 단점
    • 브라우저에서는 다운로드 progress를 볼 수 없다.
    • timeout 등의 처리를 세심하게 해 주어야 한다.

실제로 12개의 파일을 동시에 다운로드해야 했는데, (총 50GB) timeout을 처리하기 어려워서 2번 방법으로 넘아가게 되었다.

 

2. 서버에서 직접 유저에게 전달

async function download(url: string) {
  const link = document.createElement("a");
  link.href = url;
  link.target = "_blank";
  link.click();
}

브라우저 다운로드 기능을 적극 활용하여, a 태그를 만들어 가상으로 click한다.

  • 장점
    • 구현이 비교적 간단하다.
    • 브라우저에게 다운로드 기능을 위임하여, progress를 쉽게 확인할 수 있다.
  • 단점
    • filename이 서버에서 보내준 그대로 고정이다.

파일명을 바꿔주어야 했기 때문에 실제로 서버에서 추가적인 처리가 필요했다.

MinIO Presigned Url을 발급시 다음과 같이 헤더를 추가했다.

Content-Disposition: attachment; filename="filename.jpg"