웹페이지에서 파일 다운로드 링크 제공 시 파일명 설정방법
by Jingi
서비스를 만들다보면 파일 다운로드 링크를 만들어야 할 때가 있다. 이런 경우 클라우드에 파일을 업로드하고, 해당 파일의 링크를 DB에 저장해 다운로드 링크로 제공하게 된다. 이 부분을 구현하며 다운로드 파일명이 생각보다 마음대로 설정되지 않았던 문제와 이를 해결하는 경험에 대해 써봤다.
왜 다운로드할 때 파일명이 이상하지?!
보통 인터넷에서 파일을 다운로드 받을 때는 링크를 클릭한다. 이 때 설정되는 파일명이 링크의 텍스트나 특정 속성의 값으로 자동 설정되는 것인 줄 알았는데 아니었다!!!(충격)
파일 다운로드를 제공해야하는 입장에서 어떻게 파일명을 설정해야할까? 우리 팀에서 사용하는 Google Cloud Storage를 기준으로 생각해봤다.
<a>
태그의 download
속성
먼저 구글링해보니 <a>
태그의 download
속성이 파일명을 설정할 수 있도록 해준다고 나왔다.
download
속성은 연결된 URL로의 이동이 아닌 저장을 물어보게 만들어주는 속성으로, 값을 지정하면 해당 값을 파일명으로 지정해 다운로드를 제안하게된다.
<a
href="https://storage.com/some_file.txt"
download="download.txt"
>
Download
</a>
왜 아직도 다운로드 파일명이 이상하지?!
download
속성에 값을 설정하는 방법은 Same Origin URL과 blob:, data: 스킴에서만 작동하기 때문! 이라고 MDN에 친절히 나와있었다.
첨부파일 업로드 기능에서 Google Cloud Storage에 파일을 업로드하고 업로드된 파일의 URL을 DB에 저장하고 있다. 이 URL이 첨부파일 다운로드 링크로 제공되고, 결국 Cross Origin으로 접근하게 되므로 download
속성이 효과가 없다.
위 설명에 따르면 Content-Disposition
헤더가 filename을 설정할 수 있는 다른 수단으로 보였고, Content-Disposition
에 대한 설명을 읽어봤지만 어떻게 다운로드 파일명이 설정되는지 잘 모르겠어서 HTML 표준 문서를 찾아봤다.
리소스 다운로드와 관련된 HTML 표준에 따르면, Cross Origin 상황에서 브라우저는 사용자가 유해한 활동에 대한 경고를 받지않을 수 있도록 download
속성을 HTTP 응답 헤더의 (타입이 attachment
인) Content-Disposition
필드와 연관지어야 한다.
테스트에 사용한 크롬 브라우저는 상황에 맞게 Google Cloud Storage에서 보내주는 HTTP 응답 헤더를 확인하는데, Content-Disposition
필드에 filename
정보가 없어서 URL 경로의 마지막 조각을 파일명으로 저장한 것이었다.
Content-Disposition: attachment
파일명을 따로 설정하고 싶다면 Content-Disposition
필드에 ';'(세미콜론)으로 구분하고 filename
을 추가하며, 추가한 필드 값은 다음과 같다.
Content-Disposition: attachment; filename="filename.ext"
Google Cloud Storage에서 Content-Disposition
에 filename
설정 방법
무엇이 문제인지 원인을 찾았고, 이제 수정할 차례! 우리가 사용하고 있는 Google Client Storage의 Node.js 클라이언트 라이브러리 문서에서 upload()
메소드를 호출할 때 넘겨주는metadata
를 통해 contentDisposition
를 설정해 전달할 수 있다는 것을 알 수 있었다.
await bucket.upload(file.path, {
destination: 'path/in/storage',
metadata: { contentDisposition: `attachment; filename="${file.name}"` },
});
이렇게 설정해서 업로드하자 다운로드 링크를 클릭했을 때 돌아오는 HTTP 응답 헤더에도 filename
필드가 설정됐다.
Content-Disposition: attachment; filename="filename.ext"
한 번 설정해보니 Google Cloud Storage외 다른 클라우드 스토리지들도 비슷한 설정 기능을 제공해줄 것이라고 예상된다.
마무리
다운로드 링크에 사용되는 <a>
태그, <a>
태그를 해석해 동작하는 브라우저, 브라우저가 받는 HTTP 응답 헤더, 이를 보내주는 Google Cloud Storage 까지 원인을 찾아 거슬러 올라가는 이 흐름에 백엔드 지식과 프론트엔드 지식이 모두 도움이 됐다. 간단하게 생각했던 다운로드 파일명 설정으로 HTML 표준 문서까지 살펴보게될 줄은 몰랐지만, 정확한 동작 원리와 지식을 학습할 수 있는 매우 유익한 경험이었다.
참고자료
https://developer.mozilla.org/ko/docs/Web/HTML/Element/a#특성
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Disposition
https://html.spec.whatwg.org/dev/links.html#downloading-resources
https://googleapis.dev/nodejs/storage/latest/Bucket.html#upload