Partager des fichiers

Palances Liao
Palances Liao

Méthode moderne

Utiliser la méthode share() de l'API Web Share

Pour partager des fichiers, appelez navigator.share(). Notez que vous devez toujours vérifier si les fichiers peuvent être partagés avec navigator.canShare() et vous assurer que votre site utilise HTTPS avant d'appeler la méthode share().

// 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);
}

Navigateurs pris en charge

  • 89
  • 93
  • 12.1

Source

Méthode classique

La deuxième meilleure chose à proposer à l'utilisateur si l'API Web Share n'est pas prise en charge est de laisser l'utilisateur télécharger le fichier pour qu'il puisse le partager manuellement, par exemple par e-mail ou via une application de messagerie ou de réseau social en ligne.

Navigateurs pris en charge

  • 15
  • 13
  • 20
  • 10.1

Source

amélioration progressive

La méthode ci-dessous utilise l'API Web Share lorsque le navigateur le permet et lorsque les données peuvent être partagées en fonction des types de fichiers compatibles. Sinon, il revient au téléchargement du fichier.

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…');
});

Complément d'informations

Démonstration

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…');
});