使用 Web Share Target API 接收共享数据

利用 Web Share Target API 简化了移动设备和桌面设备上的分享功能

在移动设备或桌面设备上,分享应该非常简单,只需点击分享按钮、选择应用,然后选择要与谁分享即可。例如,您可以通过通过电子邮件将其发送给朋友或将其发布在 Twitter 微博中来分享有趣的文章。

过去,只有平台专用应用才能向操作系统注册,以便从其他安装式应用接收共享。不过,借助 Web Share Target API,已安装的 Web 应用可以作为分享目标向底层操作系统注册,以接收分享的内容。

一台 Android 手机,其中“分享方式”抽屉式菜单处于打开状态。
系统级分享目标选择器,其中包含已安装的 PWA 作为选项。

了解 Web Share Target 的实际运用

  1. 使用 Android 版 Chrome 76 或更高版本,或桌面版 Chrome 89 或更高版本,打开“网页分享目标”演示
  2. 出现提示时,点击安装将应用添加到主屏幕,或使用 Chrome 菜单将其添加到主屏幕。
  3. 打开任何支持分享的应用,或使用演示版应用中的“分享”按钮。
  4. 从目标选择器中,选择网站分享测试

共享后,您应该会在网络共享目标 Web 应用中看到所有共享的信息。

将您的应用注册为共享目标

如需将应用注册为分享目标,该应用需要满足 Chrome 的可安装性条件。此外,用户必须先将您的应用添加到主屏幕,然后才能向其分享内容。这可防止网站随机将自己添加到用户的分享 intent 选择器中,并确保用户希望通过您的应用执行分享操作。

更新您的 Web 应用清单

如需将应用注册为分享目标,请将 share_target 条目添加到其网站应用清单中。这会指示操作系统在 intent 选择器中将您的应用作为选项包含在内。您向清单中添加的内容会控制应用将接受的数据。share_target 条目有三种常见场景:

  • 接受基本信息
  • 接受应用更改
  • 接受文件

接受基本信息

如果目标应用仅接受数据、链接和文本等基本信息,请将以下内容添加到 manifest.json 文件中:

"share_target": {
  "action": "/share-target/",
  "method": "GET",
  "params": {
    "title": "title",
    "text": "text",
    "url": "url"
  }
}

如果您的应用已有分享网址架构,您可以将 params 值替换为现有查询参数。例如,如果您的分享网址架构使用 body 而非 text,您可以将 "text": "text" 替换为 "text": "body"

如果未提供,则 method 值默认为 "GET"enctype 字段(此示例中未显示)用于指示数据的编码类型。对于 "GET" 方法,enctype 默认为 "application/x-www-form-urlencoded",如果将其设置为其他值,系统会忽略该值。

正在接受应用更改

如果共享的数据以某种方式更改目标应用(例如,在目标应用中保存书签),请将 method 值设为 "POST" 并添加 enctype 字段。以下示例会在目标应用中创建书签,因此它会为 method 使用 "POST",并为 enctype 使用 "multipart/form-data"

{
  "name": "Bookmark",
  "share_target": {
    "action": "/bookmark",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "url": "link"
    }
  }
}

接受文件

与应用更改一样,接受文件要求 method"POST" 并且 enctype 存在。此外,enctype 必须为 "multipart/form-data",并且必须添加 files 条目。

您还必须添加一个 files 数组,用于定义应用接受的文件类型。数组元素是包含两个成员的条目:一个 name 字段和一个 accept 字段。accept 字段接受 MIME 类型、文件扩展名或包含这两者的数组。最好提供同时包含 MIME 类型和文件扩展名的数组,因为操作系统对这两者的偏好不同。

{
  "name": "Aggregator",
  "share_target": {
    "action": "/cgi-bin/aggregate",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "title": "name",
      "text": "description",
      "url": "link",
      "files": [
        {
          "name": "records",
          "accept": ["text/csv", ".csv"]
        },
        {
          "name": "graphs",
          "accept": "image/svg+xml"
        }
      ]
    }
  }
}

处理传入的内容

如何处理传入的共享数据由您决定,具体取决于您的应用。例如:

  • 电子邮件客户端可以使用 title 作为电子邮件的主题,将 texturl 串联在一起作为正文,从而起草新电子邮件。
  • 社交网络应用可以忽略 title 起草新帖子,使用 text 作为消息正文,并将 url 添加为链接。如果缺少 text,应用可能还会在正文中使用 url。如果缺少 url,应用可能会扫描 text 以查找网址,并将其添加为链接。
  • 照片分享应用可以使用 title 作为幻灯片标题、text 作为说明,以及 files 作为幻灯片图片来创建新的幻灯片。
  • 短信应用可以使用串联的 texturl 起草新消息,并舍弃 title

处理 GET 分享

如果用户选择您的应用,并且您的 method"GET"(默认值),浏览器会在 action 网址处打开一个新窗口。然后,浏览器使用清单中提供的网址编码值生成查询字符串。例如,如果分享应用提供 titletext,则查询字符串为 ?title=hello&text=world。如需处理此问题,请在前台页面中使用 DOMContentLoaded 事件监听器并解析查询字符串:

window.addEventListener('DOMContentLoaded', () => {
  const parsedUrl = new URL(window.location);
  // searchParams.get() will properly handle decoding the values.
  console.log('Title shared: ' + parsedUrl.searchParams.get('title'));
  console.log('Text shared: ' + parsedUrl.searchParams.get('text'));
  console.log('URL shared: ' + parsedUrl.searchParams.get('url'));
});

请务必使用服务工作器预缓存 action 网页,以便其快速加载并可靠运行,即使用户处于离线状态也是如此。Workbox 是一款可帮助您在服务工作器中实现预缓存的工具。

处理 POST 分享

如果您的 method"POST"(例如,目标应用接受已保存的书签或共享文件),则传入 POST 请求的正文包含共享应用传递的数据,这些数据使用清单中提供的 enctype 值进行编码。

前台页面无法直接处理此类数据。由于页面将数据视为请求,因此会将其传递给服务工作器,您可以在服务工作器中使用 fetch 事件监听器拦截该数据。然后,您可以使用 postMessage() 将数据传回前台页面,也可以将其传递给服务器:

self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  // If this is an incoming POST request for the
  // registered "action" URL, respond to it.
  if (event.request.method === 'POST' &&
      url.pathname === '/bookmark') {
    event.respondWith((async () => {
      const formData = await event.request.formData();
      const link = formData.get('link') || '';
      const responseUrl = await saveBookmark(link);
      return Response.redirect(responseUrl, 303);
    })());
  }
});

验证分享的内容

一部 Android 手机,显示了包含共享内容的演示版应用。
共享目标应用示例。

请务必验证传入的数据。遗憾的是,我们无法保证其他应用会在正确的参数中分享适当的内容。

例如,在 Android 上,url 字段将为空,因为 Android 的共享系统不支持该字段。而是通常会显示在 text 字段中,偶尔也会显示在 title 字段中。

浏览器支持

支持 Web Share Target API,如下所述:

在所有平台上,您的网站应用都必须先安装,然后才会显示为接收共享数据的潜在目标。

示例应用

显示对该 API 的支持

您打算使用 Web Share Target API 吗?您的公开支持有助于 Chromium 团队确定功能的优先级,并向其他浏览器供应商表明支持这些功能的重要性。

使用 #WebShareTarget 标签向 @ChromiumDev 发送推文,告诉我们您在哪里以及如何使用该工具。