본문 바로가기
dev/javascript

[javascript] 자바스크립트 다운로드 링크 만들기

by 최연탄 2023. 5. 1.
728x90
반응형

참고: https://levelup.gitconnected.com/how-to-download-with-javascript-1777ec0457eb

JavaScript에서 파일을 다운로드하는 방법은 여러가지가 있습니다. 이는 단일 파일을 다운로드하거나 여러 파일을 일괄 다운로드할 수 있습니다. 이 포스트에서는 이 두가지 방법을 모두 알아보겠습니다.

다운로드 링크 만들기에는 두 가지 방법이 있습니다:

  1. 단일 파일 다운로드 하기
  2. 여러 파일 다운로드 하기

단일 파일 다운로드 링크 만들기

현재 이미지가 있고 이 이미지를 다운로드 할 수 있도록 링크를 제공하고 싶다고 가정해 보겠습니다. 이 예시를 위해 링크로 만들 이미지를 만들겠습니다. 이는 오직 예시를 위한 것이며 실제로는 필요 없을 수도 있습니다.

function createImage(text) {
    const oldCanvas = document.createElement('canvas');
    const ctx = oldCanvas.getContext('2d');
    const font = "50px serif";
    ctx.font = font;
    ctx.fillStyle = 'black';
    ctx.font = font;
    ctx.fillText(text, 10, 100);
    return oldCanvas.toDataURL();
}

이 함수의 세부 내용은 중요치 않습니다. 중요한 것은 함수가 이미지 파일의 URL을 리턴한다는 것 입니다.

더 중요한 부분은 다음 입니다:

const container = document.getElementById('image-container'); // 컨테이너 얻기
const dataURL = createImage("pandaquests"); // 이미지 얻기

const anchor = document.createElement('a'); // 다운로드를 위한 a 요소 생성
anchor.href = dataURL; // 다운로드 링크 설정 <-- 중요
anchor.download = `test.png`; // 다운로드 파일 이름 설정 <-- 중요
const button = document.createElement('button'); // 다운로드 버튼 생성
button.innerHTML = 'Download'; // 다운로드 버튼 이름 설정
anchor.appendChild(button); // 링크에 버튼 연결
container.appendChild(anchor); // 컨테이너에 링크 연결

위의 코드에서 두 줄을 "중요"로 표시했습니다. 먼전 href를 createImage() 함수에서 가져온 이미지 URL의 변수인 dataURL로 설정합니다. 두 번째는 다운로드 속성을 원하는 파일 이름으로 설정하는 것 입니다. 이렇게 하면 링크를 다운로드할 수 있습니다. 다른 모든 부분은 컨트롤(버튼)을 생성하고 HTML에서 "image-container"와 같은 요소에 추가하기 위한 것 입니다.

지금 까지 단일 파일(이 경우 이미지)을 다운로드하기 위한 링크를 만들어 봤습니다.

여러 파일에 대한 다운로드 링크 생성

여러 파일을 다운로드하는 경우 대부분의 브라우저는 다운로드 요청을 6~10개의 동시 다운로드로 제한하기 때문에 단일 파일에 대한 다운로드링크를 여러번 호출할 수 없습니다. 그 이상을 다운로드하려면 여러 파일이 포함된 zip 파일을 만들고 zip 파일을 다운로드 하면 됩니다.

zip 파일을 위해 jszip 라이브러리가 필요합니다.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.2.2/jszip.min.js"></script>

다운로드를 실행하기 위해 Filesaver 라이브러리가 필요합니다.

<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.21.15/plugins/export/libs/FileSaver.js/FileSaver.min.js"></script>

코드는 다음과 같습니다.

const zip = new JSZip(); // JSZip 인스턴스 생성

for (let i = 0; i < 10; i++) {
    const fileName = "pandaquests" + i;
    const dataURL = createImage(fileName); // 이미지 얻기
    const blob = dataURLToBlob(dataURL); // blob 만들기
    zip.file(`${fileName}.png`, blob, { binary: true }); // zip 파일에 추가
}

const bulkDownload = document.getElementById('buldDownload'); // 버튼 얻기

bulkDownload.addEventListener('click', () => {
    // zip 파일을 Blob으로 만들기
    zip.generateAsync({ type: "blob" }).then(zipFile => {           
        saveAs(zipFile, 'bulk.zip'); // zip 파일 다운로드 실행
    });
});

먼저 JSZip 객체를 만듭니다. 이는 zip 파일을 생성할 것 입니다. 그 다음 zip 파일을 여러개의 파일로 채웁니다. for 루프에 있는 고드의 세부 사항은 그리 중요하지 않습니다. 중요한 것은 zip 객체에 모든 단일 파일을 넣는 것입니다.

for 루프는 dataUrl을 blob으로 바꾸기 위해 dataURLToBlob 함수를 사용합니다. 기능은 다음과 같습니다.

function dataURLToBlob(dataURL) {
    // url을 metadata 부분과 data 부분으로 나눔
    const parts = dataURL.split(';base64,');
    const metadata = parts[0];
    const data = atob(parts[1]);

    // ArrayBuffer 생성
    const buffer = new ArrayBuffer(data.length);
    const view = new Uint8Array(buffer);

    // data를 view에 복사
    for (let i = 0; i < data.length; i++) {
        view[i] = data.charCodeAt(i);
    }

    // blob 리턴
    return new Blob([view], { type: metadata.split(':')[1] });
}

여기서 초점은 다운로드 링크를 생성하느 것이기 때문에 위의 코드에 대해 자세히 설명하지는 않겠습니다. 간단히 위의 코드는 base64를 사용하여 atob() 함수와 Blob 생성자를 사용하여 URL을 Blob으로 변환하는 것입니다.

다음으로 zip 파일을 다운로드하기 위한 click 이벤트 핸들러를 추가하고 JSZip 객체가 zip 파일을 생성합니다. 이 작업이 완료되면 FileSaver 라이브러리에서 saveAs() 함수를 실행합니다. 이 작업이 완료되면 (사용자가 클릭해서 클릭 이벤트를 발생시키면) zip 파일이 다운로드 됩니다.

관련 글

자바스크립트 createElement 사용 방법

자바스크립트 버튼 클릭

반응형

댓글