javascripthtmlweb-applicationsweb-share

navigator.share file not working on iOS 14 Safari


I'm trying to add to my webpage an option to share image and video using Web Share API. When testing it, I'm having the following problem: on Android + Chrome, it works sharing video and images, but when I execute the same code on iOS 14.4 Safari (running on iPhone 6s) I only get the text and URL sharing, not the files. Is someone having the same issue? Based on this it was supposed to work: https://caniuse.com/web-share

https://jsfiddle.net/ryb0x537/

Regards.

<div id="error"></div>
<form method="POST" action="/share/">
  <table>
    <tr>
      <td><label for="shared_title">Title:</label></td>
      <td><input id="shared_title" name="shared_title" value="Example Title"></td>
    </tr>
    <tr>
      <td><label for="shared_text">Text:</label></td>
      <td><input id="shared_text" name="shared_text" value="Example text"></td>
    </tr>
    <tr>
      <td><label for="shared_url">URL:</label></td>
      <td><input id="shared_url" name="shared_url" value="https://example.com/a?b=c"></td>
    </tr>
    <tr>
      <td><label for="shared_file">File(s):</label></td>
      <td><input id="shared_file" name="shared_file" type="file" multiple></td>
    </tr>
  </table>
  <input type="submit" value="Share">
</form>
<script>
document.querySelector('form').onsubmit = () => {
  const error = document.getElementById('error');
  const title = document.getElementById('shared_title').value;
  const text = document.getElementById('shared_text').value;
  const url = document.getElementById('shared_url').value;
  const files = document.getElementById('shared_file').files;

  let data = {};
  if (files.length > 0) {
    data.files = files;
  }
  if (title !== '')
    data.title = title;
  if (text !== '')
    data.text = text;
  if (url !== '')
    data.url = url;

  error.textContent = '';
  navigator.share(data)
    .then(() => {
  })
    .catch((err) => {
    console.log('Unsuccessful share');
    error.textContent = 'Share failed: ' + err.message;
  });

  return false;
};
</script>


Solution

  • It seems like Safari has trouble with file objects and chokes (throws a TypeError). I could get it to work by using blobs converted to files instead:

    const blob = await fetch('https://cdn.glitch.com/f96f78ec-d35d-447b-acf4-86f2b3658491%2Fchuck.png?v=1618311092497').then(r=>r.blob())
    
    const share = async (title, text, blob) => {
      const data = {
        files: [
          new File([blob], 'image.png', {
            type: blob.type,
          }),
        ],
        title: title,
        text: text,
      };
      try {
        if (!(navigator.canShare(data))) {
          throw new Error('Can\'t share data.', data);
        };
        await navigator.share(data);
      } catch (err) {
        console.error(err.name, err.message);
      }
    };