跳转到内容

接收分享的内容(share target)

发布于 更新于

完成本指南后,你的已安装 PWA 会出现在操作系统的分享面板中,从别的应用分享过来的一张照片会以 File 的形式落到你的页面里,供预览与导入。Web App Manifest 中的 share_target 声明接收 URL;浏览器随后像 表单提交一样向它发起 GET 或 POST,剩下的就是你熟悉的请求处理。

你需要一个带 Service Worker 的可安装 PWA(见让它可安装);在所有平台上, 分享面板都只在用户安装之后才列出 Web 应用。每个 manifest 只允许一个 share_target,所以不同类型的分享 在落地页上分流,而不是声明多个。

action(接收 URL,须在 manifest 的 scope 之内)与 params(分享字段到请求参数名的映射)是必需的。 method 默认为 GET,enctype 默认为 application/x-www-form-urlencoded。接收文件要求 POST 配合 multipart/form-data,并提供一个 files 数组,每一项写明字段名与接受的 MIME 类型或扩展名;两种写法都列上, 因为各操作系统匹配的方式不同。

{
"name": "Scrapbook",
"start_url": "/",
"display": "standalone",
"share_target": {
"action": "/share",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"title": "title",
"text": "text",
"url": "url",
"files": [{ "name": "media", "accept": ["image/*", ".png", ".jpg", "video/*"] }]
}
}
}

纯文本目标可以保留 GET 默认值:浏览器以 ?title=…&text=…&url=… 打开 action,页面读取 new URL(location).searchParams。GET 更容易调试,但会把分享的文本泄露到历史记录与服务器日志里; POST 把它放在请求体中,而且是接收文件的唯一方式。

页面读不到 POST 请求体,所以由 Service Worker 在 fetch 中拦截请求、读取 formData()、保存文件, 然后以 303 See Other 重定向到展示它们的页面。重定向很重要:它阻止刷新页面时再次提交这次分享。 重定向目标带一个标记(?shared=1),页面据此知道要去缓存里找。

sw.js
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
if (event.request.method !== 'POST' || url.pathname !== '/share') return;
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/${i}`, new Response(file))));
const text = formData.get('text') || formData.get('url') || '';
return Response.redirect(`/share/view?shared=1&text=${encodeURIComponent(text)}`, 303);
})(),
);
});

像对待任何表单提交一样校验收到的内容:别的应用会把内容放进意料之外的参数,而请求体来自你无法控制的软件。

被重定向到的页面检查标记,把保存的响应读回为 Blob,展示出来供确认,然后删除它们, 以免第二次分享捡到第一次的文件。不带标记直接打开 /share/view 时渲染正常视图。

function isSharedLaunch() {
return new URLSearchParams(location.search).has('shared');
}
async function takeSharedFiles() {
if (!('caches' in window)) return [];
const cache = await caches.open('shared-content');
const requests = await cache.keys();
const files = await Promise.all(requests.map((request) => cache.match(request).then((r) => r.blob())));
await Promise.all(requests.map((request) => cache.delete(request)));
return files;
}
if (isSharedLaunch()) {
takeSharedFiles().then(renderSharedFiles);
} else {
renderDefaultView();
}

从浏览器的 Install(英文界面)入口安装 PWA,打开任意相册应用,选择 Share,在系统面板中选中你的 应用名。重定向落到 /share/view,预览图由缓存的文件渲染出来。再从浏览器分享一个 URL,就能看到 Android 上 text 回退的实际效果。会在分享面板中提供已安装 Web 应用的浏览器列在下表:

  • 图例
  • 支持
  • 部分支持
  • 需开启标志
  • 不支持
  • 未知
浏览器 / 平台支持版本置信度来源备注
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 · 置信度: 低 (由来源计算)

← 返回指南总览。