1

How can I share a file using Web Share Target API?

I managed to make my Progressive Web App appear when I try to share a file from the gallery app on my phone. My question is how can I take the file and send it to the server or fill a HTML input with type="file" with the shared file?

This is what I have right now

In manifest.json

    "share_target": {
    "action": "/qtransfer-p/send.php",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "title": "name",
      "text": "description",
      "url": "link",
      "files": [
        {
          "name": "fileToUpload",
          "accept": [".pdf", ".png", ".jpeg", ".doc", ".docx", ".pdf", ".xls", ".xlsx", ".txt", ".mp4", ".mp3", ".wav", ".rar", ".zip"]
        }
      ]
    }
}

In sw.js (service worker)

self.addEventListener('fetch', event => {
  const url = new URL(event.request.clone().url);
  // If this is an incoming POST request for the
  // registered "action" URL, respond to it.
  if (event.request.method === 'POST' &&
      url.pathname === '/qtransfer-p/send.php') {
      event.respondWith(Response.redirect('/qtransfer-p/send.php'));
      event.waitUntil((async () => {
        console.log("1");
        const data = await event.request.clone().formData();
        console.log("2");
        console.log(data);
        const client = await self.clients.get(event.resultingClientId || event.clientId);
        console.log("3");
        const file = data.get("fileToUpload");
        console.log("file", file);
        client.postMessage({ file, action: 'load-file' });
      })());
      console.log("ok");
      return 0;
  }
});

Right now, when I share a photo, I get in console:

1

ok

Uncaught (in promise) TypeError: Failed to fetch

So I think the problem is on the "const data = await event.request.clone().formData();".

Someone please help! I am trying to solve this for 2 weeks!

Paul T.
  • 25
  • 5

1 Answers1

2

If you'd like to send a file directly to your web server, you can skip the service worker involvement.

Your current manifest.json setup will result in a POST request being sent to the /qtransfer-p/send.php at your origin, encoded as multipart/form-data, whenever someone shares a supported file to your installed PWA.

As long as you don't intercept that request in a service worker, I believe it will just be sent directly like any other HTTP POST, and could be processed server-side.

Jeff Posnick
  • 53,580
  • 14
  • 141
  • 167
  • I understand how this would work but when I try to take the form data in upload.php (The file that actually encrypts and uploads to server + some SQL stuff), I can't seem to make it work. To be more precise: send.php has a form which sends a POST with a selected file. upload.php takes that POST, which contains the filename and the contents then uploads the file to a folder on my server. So how can I, instead of manually selecting a file on send.php, I would press share (in gallery app) and upload.php takes the file like it was selected in send.php (selected in a )? – Paul T. Apr 17 '21 at 07:24
  • Right now in upload.php I have something like `$filename = basename($_FILES["fileToUpload"]["name"]);` – Paul T. Apr 17 '21 at 07:29
  • 1
    I think that changing the `action` in your web app manifest to `/path/to/send.php` would accomplish what you describe? The details of the `POST` request that your `action` URL receives, including the encoding type and the name of fields is also determined by your web app manifest. – Jeff Posnick Apr 20 '21 at 14:08
  • Well I did that but still can't seem to get it to work. My browser registers a `POST` request to `upload.php` but there is no data being sent. My PHP is right so I really think that the problem is somewhere in the manifest. There is not data sent through that `POST` – Paul T. Apr 20 '21 at 16:41