본문 바로가기
IT

[HTML] a 태그를 이용한 다운로드 기능

by Redking

HTML에는 a태그라는 하이퍼링크를 걸어주는 태그가 존재합니다. 주로 href, target, onclick과 같은 속성을 사용하였는데 a태그에 download 속성을 이용하면 href에 지정한 파일을 다운로드 할 수 있다는 글을 읽고 블로그에 공유하게 되었습니다. 이미지 다운로드 같은 경우에 일반적으로 이미지에 우클릭하여 다운로드 하는게 익숙하지만 이 기능은 이미지 뿐만 아니라 다양한 파일에 대해서 [다운로드] 버튼을 눌렀을때 다운로드가 가능하기 때문에 확정성 측면에서 상위 호환하는 기능이라 생각되어 공유하게 되었습니다.

 

예시)

<a href="/temp/text.txt" download="텍스트_파일">파일 다운로드</a>

위 코드대로 구현하여 파일 다운로드 버튼을 클릭하면 텍스트_파일.txt가 다운로드 되게 됩니다. 어떤 원리인지 짚어보면 href에 들어가는 값은 다운로드될 파일의 경로이고 download에 들어가는 값은 다운로드 될 파일의 이름입니다. download에 들어갈 값은 필수 값이 아니며 입력하지 않는 경우에는 href에 지정된 경로의 파일 명 그대로 다운로드(text.txt) 됩니다. 단 download은 필수로 입력해 다운로드가 원활하게 진행되니 주의하셔야 합니다.

 

추가 처리사항

보안 이슈로 인하여 2018년 말부터 다운로드할 리소스가 동일한 출처 또는 동일한 서버에서 제공되지 않은 경우 링크를 클릭해도 다운로드가 트리거되지 않게 되었는데요, 이 이슈를 해결하는 방법은 여러 종류가 존재합니다.

 

Data URI

데이터 URI는 리소스의 base64 인코딩이므로 외부 리소스에 연결할 필요가 없으며 텍스트 자체가 리소스입니다.

<a href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQ..." 
   download="텍스트_파일"
>파일 다운로드</a>

Blob URL

리소스를 base64로 변환하는 대신 blob URL로 변환하는 방식이 더 좋은 해결책입니다.

function Download({ url, filename }) {
   const [fetching, setFetching] = useState(false);
  const [error, setError] = useState(false);

  const download = (url, name) => {
    if (!url) {
      throw new Error("Resource URL not provided! You need to provide one");
    }
    setFetching(true);
    fetch(url)
      .then(response => response.blob())
      .then(blob => {
        setFetching(false);
        const blobURL = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = blobURL;
        a.style = "display: none";

        if (name && name.length) a.download = name;
        document.body.appendChild(a);
        a.click();
      })
      .catch(() => setError(true));
  };

  return (
    <button
      disabled={fetching}
      onClick={()=> download(url, filename)}
      aria-label="download"
    >
      DOWNLOAD
    </button>
  );
}

Content-Disposition

HTTP 헤더 Content-Disposition:이 있고 이 특성과 다른 파일 이름을 제공하는 경우 HTTP 헤더가 이 특성보다 우선합니다.

이 속성이 있고 Content-Disposition:이 인라인으로 설정된 경우 Firefox는 파일 이름 대소문자와 같이 Content-Disposition에 우선 순위를 부여하고 Chrome은 다운로드 속성에 우선 순위를 부여합니다.

Content-Disposition: attachment

Cross Origin 상황에서 브라우저는 사용자가 유해한 활동에 대한 경고를 받지않을 수 있도록 download 속성을 HTTP 응답 헤더의 Content-Disposition 필드와 연관지어야하고 테스트에 사용한 크롬 브라우저는 상황에 맞게 Google Cloud Storage에서 보내주는 HTTP 응답 헤더를 확인하는데, Content-Disposition 필드에 filename 정보가 없어서 URL 경로의 마지막 조각을 파일명으로 저장한 것이 었습니다.

파일명을 따로 설정하고 싶다면 Content-Disposition 필드에 ';'(세미콜론)으로 구분하고 filename을 추가하며, 추가한 필드 값은 다음과 같습니다.

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

'IT' 카테고리의 다른 글

코드 품질, 기술 부채  (0) 2024.03.07
chat gpt한태 코드 짜달라고 하기  (0) 2023.03.15
배달앱  (0) 2022.08.13
디지털 IC  (0) 2022.08.13
운영체제의 종류  (0) 2022.08.13

댓글