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

使用 Web Share Target API 轻松在移动设备和桌面设备上进行分享

在移动设备或桌面设备上,分享操作应该简单到只需点击分享按钮、选择应用并选择分享对象即可。例如,您可能希望通过电子邮件将一篇有趣的文章发送给朋友,或者将其发布到 Twitter 上,分享给全世界。

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

Android 手机,其中的“分享方式”抽屉式导航栏处于打开状态。
系统级共享目标选择器,可以选择已安装的 PWA。

了解网络分享目标的实际效果

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

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

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

如需将应用注册为共享目标,该应用必须符合 Chrome 的可安装性标准。此外,用户必须先将其添加到自己的主屏幕,然后才能与您的应用分享。这样可以防止网站随机将自己添加到用户的分享 intent 选择器,并确保用户希望通过您的应用进行分享。

更新 Web 应用清单

如需将应用注册为共享目标,请将 share_target 条目添加到其 Web 应用清单中。它会指示操作系统将您的应用作为一个选项添加到 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'));
});

请务必使用 Service Worker 来预缓存 action 页面,使其快速加载并可靠地运行,即使用户处于离线状态也是如此。Workbox 是一款工具,可帮助您在 Service Worker 中实现预缓存

正在处理 POST 分享内容

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

前台网页无法直接处理此类数据。由于页面将数据视为请求,因此该页面会将其传递给 Service Worker,您可以在其中使用 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 受支持,如下所述:

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

示例应用

显示对该 API 的支持

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

请使用 # 标签 #WebShareTarget@ChromiumDev 发送一条推文,并告诉我们您使用该产品的位置和方式。