Photo by Maksym Kaharlytskyi on Unsplash
iframe 을 사용한 Cross-Origin 파일 다운로드 하기
+ 파일 다운로드 UX 를 고려한 여러 고민들
개요
회사에서 화상 미팅 서비스에 대용량이 가능한 채팅 파일 공유 기능을 개발하고 있다. 파일 공유로 S3 presigned URL
을 받아오고 있다. 이 URL 을 다운로드 받기 위해서 a 태그를 사용할 수 없었다. 이유는 a 태그의 download 속성은 Same-Origin URL, blob:
, data:
스킴에서만 동작한다. [참고]
target="_blank"
속성을 주는 방법도 있었지만 그렇게 된다면 화상미팅 도중 공유된 파일 확인 시 새탭으로 이동하게 되어 미팅 UX 가 나빠질 우려가 있었다.
해당 문제를 해결하기 위해 여러가지 레퍼런스 조사를 진행했고, 여러 테스트를 거쳐 iframe 을 사용하는 방법으로 이슈를 해결했다.
주의사항
먼저 설명하기에 앞서 주의해야 할 사항이 두가지 존재한다.
다운로드 받을 파일에
Content-Disposition: attachment
HTTP 헤더가 있어야 한다. [참고]iOS 에서는 동작하지 않는다.
- iOS 에서 동작하지 않는 이유는 sandbox 속성의
allow-downloads
를 지원하지 않아서라고 생각한다. [참고]
- iOS 에서 동작하지 않는 이유는 sandbox 속성의
iframe src 를 활용한 파일 다운로드
const isIos = () => window.navigator.userAgent.match(/ipad|iphone/i) !== null;
const download = (url) => {
if (isIos()) {
window.open(url, '_blank');
return;
}
const iframe = document.createElement('iframe');
iframe.src = url;
iframe.style.display = 'none';
document.body.appendChild(iframe);
};
DOM 트리에
iframe
이 추가 되면서 파일을 불러오게 되고Content-Disposition
헤더로 파일 다운로드가 시작된다.생성한
iframe
의 src 를 변경하는것 만으로 다른 파일도 다운로드 받을 수 있다.
iframe 내부 anchor 태그로 파일 다운로드
const isIos = () => window.navigator.userAgent.match(/ipad|iphone/i) !== null;
const download = (url, fileName = '') => {
const iframe = document.createElement('iframe');
iframe.src = 'about:blank';
iframe.style.display = 'none';
document.body.appendChild(iframe);
const anchor = iframe.contentDocument.createElement('a');
anchor.download = fileName ;
anchor.href = url;
if (isIos()) {
anchor.target = '_blank';
}
iframe.contentDocument.body.appendChild(anchor);
anchor.click();
};
- 이 방법으로도 파일을 다운로드 받을 수 있다.
파일 다운로드 기능을 개발하기위한 여러 시도들
했던 시도들이 아쉬워서 글 끄트머리에 넣어보려고 한다.
Next.js Middleware 의 rewrites 시도 +
<a download />
Ctrl + Click
액션 재현 시도window.focus
를 활용해 현재 탭 포커싱 유지 시도
이 중 Next.js 시도에 대해 얘기 해보려고 한다. Next.js 의 Middleware 를 사용하지 않은 이유는 두가지가 있었는데,
첫째는 현재 진행중인 프로젝트가 AWS CodeBuild
를 통해 ECS 로 Blue/Green 배포 방식이 적용된 상태이다. rewrites 를 통해 다운로드 받은 시점의 CPU 사용량을 체크해보니 최대 평균 사용량이 1% → 10% 로 크게 증가한 모습을 보였다.
둘째는 rewrites 를 통해 대용량 파일을 다운로드 받을 시 서버가 꺼지게 되면 네트워크 에러로 다운로드가 실패 한다. Blue/Green 배포 테스트를 해보니 짧은 시간 순단이 발생하는 상황이 발생했다.
마무리
iframe
을 통한 두가지 다운로드 방법은 아래 URL 을 통해 직접 테스트 해 볼 수 있다.