跳转到内容

接收分享的内容(share target)

发布于 更新于

一句话概括: 在 Web App Manifest 中声明 share_target,会将已安装的 PWA 注册到操作系统 原生的分享面板中,这样其他应用就可以直接把 URL、文本、标题和文件分享到你的应用,而不需要 你自己搭建一套单独的导入流程。

根据 MDN 的说明,share_target 需要一个 action(接收分享内容的 URL)和 params (分享字段到请求参数的映射);method 与 enctype 是可选的,默认分别为 "GET" 与 "application/x-www-form-urlencoded":

{
"share_target": {
"action": "/share-handler",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"title": "title",
"text": "text",
"url": "url",
"files": [
{ "name": "media", "accept": ["image/*", "video/*"] }
]
}
}
}

默认的 GET 且不带 files 就足以接收纯文本/URL 分享;接收文件则必须显式设置 "method": "POST" 与 "enctype": "multipart/form-data",这一点来自 MDN 的说明。

当操作系统在分享面板中提供了你的应用、且用户选择了它之后,浏览器会向 action 发送 一个 POST(或 GET)请求,其形式与表单提交完全一致。在 Service Worker 的 fetch 处理程序中拦截该请求并读取分享的数据。MDN 表示,POST 分享请求最好以 303 重定向响应, 以避免刷新时重复提交 POST;Chrome for Developers 也演示了这种模式:

self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
if (event.request.method === 'POST' && url.pathname === '/share-handler') {
event.respondWith((async () => {
const formData = await event.request.formData();
const files = formData.getAll('media');
const cache = await caches.open('shared-content');
await Promise.all(
files.map((file, i) => cache.put(`/shared-file-${i}`, new Response(file)))
);
// 重定向(带上应用检测分享启动所需的标记)到一个会把缓存的文件读回来的页面。
return Response.redirect('/share-handler/view?shared=1', 303);
})());
}
});

被重定向到的页面会读取 Service Worker 存储的内容——也就是上面缓存的文件——并在导入前 展示给用户:

async function loadSharedFiles() {
const cache = await caches.open('shared-content');
const keys = await cache.keys();
const files = await Promise.all(
keys
.filter((req) => req.url.includes('/shared-file-'))
.map((req) => cache.match(req).then((res) => res.blob()))
);
return files;
}

share_target 具体支持哪些浏览器、平台与版本,请参见下方的兼容性数据:

  • 图例
  • 支持
  • 部分支持
  • 需开启标志
  • 不支持
  • 未知
浏览器 / 平台支持版本置信度来源备注
Chrome (Android)支持76低来源—
Edge (Desktop)支持89低来源1
Samsung Internet支持12.0低来源—
Firefox (Desktop)不支持—低来源2
Safari (iOS)不支持—低来源3
Safari (macOS)不支持—低来源4
  1. GET 模式下对文件的支持有限。
  2. 桌面端没有使用 share_target 的安装路径。
  3. iOS 上不支持。
  4. macOS 上不支持。

源数据: /compatibility/manifest-share-target.json · 全球使用占比: 72 % (StatCounter 2026-05)

来源: 规范 · MDN · 最近核验 2026-07-11 · 置信度: 低 (由来源计算)

此示例自行在重定向中添加了 shared 查询参数。页面可以检测这条由应用定义的重定向路径, 并在未检测到时渲染正常视图:

function isSharedRedirect() {
return new URLSearchParams(location.search).has('shared');
}
async function loadSharedFiles() {
if (!('caches' in window)) {
// 当前上下文不支持 Cache Storage——没有可读回的内容。
return [];
}
const cache = await caches.open('shared-content');
const keys = await cache.keys();
return Promise.all(
keys
.filter((req) => req.url.includes('/shared-file-'))
.map((req) => cache.match(req).then((res) => res.blob()))
);
}
if (isSharedRedirect()) {
loadSharedFiles().then(renderSharedFiles);
} else {
// 不存在应用定义的重定向标记——渲染正常的初始视图。
renderDefaultView();
}
  • share_target 只对已安装的 PWA 生效——未安装的普通标签页不会出现在操作系统 的分享面板中。
  • 根据 MDN 的说明,接收文件需要 "method": "POST" 与 "enctype": "multipart/form-data"——仅支持 GET 的目标无法接收 files。
  • 处理 POST 后优先使用 303 重定向;MDN 称这是避免刷新页面时重复提交 POST 的 理想做法。
  • 为被重定向到的路由提供一个由应用定义的标记(例如查询参数),这样当它被直接打开时 可以回退到正常界面。
  • 在读取分享的文件后清除或使其过期,避免重复分享导致陈旧数据不断累积。