pile·
프론트엔드·레모네이드레모네이드·

웹페이지에서 파일 다운로드 링크 제공 시 파일명 설정방법

파일 다운로드 링크를 만들었는데 저장되는 파일명이 마음대로 정해지지 않는 문제를 HTML 표준까지 거슬러 올라가 원인을 밝히고 고친 기록이다. `<a download>` 가 왜 안 먹는지, 브라우저가 실제로 무엇을 보고 파일명을 정하는지, Google Cloud Storage 쪽에서 무엇을 설정해야 하는지가 순서대로 나온다.

핵심 포인트
  • 다운로드 파일명은 링크 텍스트나 특정 속성으로 자동 결정되지 않는다.
  • `<a>` 태그의 `download` 속성으로 파일명을 지정할 수 있지만, Same Origin URL 과 `blob:`, `data:` 스킴에서만 작동한다.
  • 클라우드 스토리지에 올린 파일 URL 을 그대로 쓰면 Cross Origin 이 되어 `download` 속성이 무력화된다.
  • HTML 표준은 Cross Origin 상황에서 브라우저가 `download` 속성을 응답 헤더의 `Content-Disposition`(type 이 attachment) 와 연관지어야 한다고 규정한다.
  • `Content-Disposition` 에 filename 정보가 없으면 브라우저는 URL 경로의 마지막 조각을 파일명으로 쓴다. 이것이 이상한 파일명의 정체였다.
상세 정리
  • 상황: 첨부파일을 Google Cloud Storage 에 올리고 그 URL 을 DB 에 저장해 다운로드 링크로 제공하는 흔한 구성이다.
  • 1차 조사: 구글링으로 `download` 속성을 찾았다. 이 속성은 URL 로 이동하는 대신 저장을 묻게 만들고, 값을 주면 그 값을 파일명으로 제안한다.
  • 벽: 그런데도 파일명이 그대로였다. MDN 에 "Same Origin URL 과 blob:, data: 스킴에서만 작동한다" 고 적혀 있었다.
  • 2차 조사: MDN 의 `Content-Disposition` 설명만으로는 파일명이 어떻게 정해지는지 알 수 없어 HTML 표준의 리소스 다운로드 항목을 직접 찾아봤다.
  • 표준이 그렇게 규정한 이유는 사용자가 유해한 활동에 대한 경고를 받지 못하는 상황을 막기 위해서다.
  • 검증: 크롬으로 테스트해 Google Cloud Storage 가 보내는 응답 헤더를 확인했더니 `Content-Disposition` 에 filename 이 없었다.
  • 형식: 파일명을 지정하려면 `Content-Disposition` 값에 세미콜론으로 구분해 filename 을 붙인다.
  • 수정: Google Cloud Storage 의 Node.js 클라이언트 라이브러리에서 `upload()` 호출 시 넘기는 metadata 로 `contentDisposition` 을 설정할 수 있었다.
  • 결과: 그렇게 업로드한 파일은 다운로드 링크 클릭 시 응답 헤더에 filename 이 실려 오고 의도한 이름으로 저장된다.
  • 일반화: 다른 클라우드 스토리지도 비슷한 설정 기능을 제공할 것으로 본다.
  • 회고: `<a>` 태그 → 브라우저 해석 → HTTP 응답 헤더 → 스토리지 설정 순으로 거슬러 올라가는 과정에 프론트엔드와 백엔드 지식이 모두 필요했다고 정리한다.
왜 읽나클라우드 스토리지 링크로 파일을 내려받게 했는데 파일명이 해시나 경로 조각으로 저장돼 곤란했던 개발자에게 정확한 원인과 수정 지점을 준다.
레모네이드
레모네이드 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    항공 프론트엔드 구축기 (7/10): 창구를 하나만 두었습니다

    여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.

    요약 이어보기
    #react#typescript#webview+2