파일 공유 방법

팔란스 리아오
Palances Liao

현대적인 방식

Web Share API의 share() 메서드 사용

파일을 공유하려면 navigator.share()를 호출합니다. share() 메서드를 호출하기 전에 항상 파일을 navigator.canShare()와 공유할 수 있는지 확인하고 사이트에서 HTTPS를 사용하는지 확인해야 합니다.

// Assume `blob` is a PNG image file.
const data = {
  files: [
    new File([blob], 'image.png', {
      type: blob.type,
    }),
  ],
  title: 'My title',
  text: 'My text',
};
if (navigator.canShare(data)) {
  await navigator.share(data);
}

브라우저 지원

  • 89
  • 93
  • 12.1

소스

기존의 방식

Web Share API가 지원되지 않는 경우 사용자에게 제안할 차선책은 사용자가 파일을 다운로드해 이메일이나 메신저, 온라인 소셜 네트워크 앱 등을 통해 수동으로 공유할 수 있게 하는 것입니다.

브라우저 지원

  • 15
  • 13
  • 20태국 바트
  • 10.1

소스

점진적 개선

아래 방법에서는 브라우저에서 지원되는 경우 및 지원되는 파일 형식에 따라 데이터를 공유할 수 있는 경우 Web Share API를 사용합니다. 그렇지 않으면 파일을 다운로드하는 방식으로 대체됩니다.

const button = document.querySelector('button');
const img =  document.querySelector('img');

// Feature detection
const webShareSupported = 'canShare' in navigator;
// Update the button action text.
button.textContent = webShareSupported ? 'Share' : 'Download';

const shareOrDownload = async (blob, fileName, title, text) => {
  // Using the Web Share API.
  if (webShareSupported) {
    const data = {
      files: [
        new File([blob], fileName, {
          type: blob.type,
        }),
      ],
      title,
      text,
    };
    if (navigator.canShare(data)) {
      try {
        await navigator.share(data);
      } catch (err) {
        if (err.name !== 'AbortError') {
          console.error(err.name, err.message);
        }
      } finally {
        return;
      }
    }
  }
  // Fallback implementation.
  const a = document.createElement('a');
  a.download = fileName;
  a.style.display = 'none';
  a.href = URL.createObjectURL(blob);
  a.addEventListener('click', () => {
    setTimeout(() => {
      URL.revokeObjectURL(a.href);
      a.remove();
    }, 1000)
  });
  document.body.append(a);
  a.click();
};

button.addEventListener('click', async () => {
  const blob = await fetch(img.src).then(res => res.blob());
  await shareOrDownload(blob, 'cat.png', 'Cat in the snow', 'Getting cold feet…');
});

추가 자료

데모

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      rel="icon"
      href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎉</text></svg>"
    />
    <title></title>
    <link rel="stylesheet" href="style.css" />
    <!-- TODO: Devsite - Removed inline handlers -->
    <!-- <script src="script.js" type="module"></script> -->
  </head>
  <body>
    <h1>Share a file</h1>
    <img
      width="200"
      height="200"
      alt="A cat walking in the snow."
      src="cat.png"
    />
    <button type=button></button>
  </body>
</html>

CSS


        :root {
  color-scheme: dark light;
}

html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

body {
  margin: 1rem;
  font-family: system-ui, sans-serif;
}

img,
video {
  height: auto;
  max-width: 100%;
  display: block;
}

button {
  margin: 1rem;
}
        

JS


        const button = document.querySelector('button');
const img =  document.querySelector('img');

const webShareSupported = 'canShare' in navigator;
button.textContent = webShareSupported ? 'Share' : 'Download';

const shareOrDownload = async (blob, fileName, title, text) => {
  if (webShareSupported) {
    const data = {
      files: [
        new File([blob], fileName, {
          type: blob.type,
        }),
      ],
      title,
      text,
    };
    if (navigator.canShare(data)) {
      try {
        await navigator.share(data);
      } catch (err) {
        if (err.name !== 'AbortError') {
          console.error(err.name, err.message);
        }
      } finally {
        return;
      }
    }
  }
  // Fallback
  const a = document.createElement('a');
  a.download = fileName;
  a.style.display = 'none';
  a.href = URL.createObjectURL(blob);
  a.addEventListener('click', () => {
    setTimeout(() => {
      URL.revokeObjectURL(a.href);
      a.remove();
    }, 1000)
  });
  document.body.append(a);
  a.click();
};

button.addEventListener('click', async () => {
  const blob = await fetch(img.src).then(res => res.blob());
  await shareOrDownload(blob, 'cat.png', 'Cat in the snow', 'Getting cold feet…');
});