วิธีสมัยใหม่
การใช้ Web Share Target API
ก่อนอื่น ให้ประกาศ share_target
ในไฟล์ Manifest ของเว็บแอปที่แสดงรายการ action
(URL ของคุณที่จัดการไฟล์ที่แชร์), method
("POST"
สำหรับไฟล์) และ enctype
("multipart/form-data"
สำหรับไฟล์) และออบเจ็กต์ params
ที่มีพร็อพเพอร์ตี้ files
พร้อมอาร์เรย์ของออบเจ็กต์ที่มีพร็อพเพอร์ตี้ name
และ accept
ซึ่งแสดงประเภทไฟล์ที่แชร์ได้และชื่อที่จะรับไฟล์
{
"share_target": {
"action": "/receive-files/",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"files": [
{
"name": "image",
"accept": ["image/jpeg", "image/png", "image/webp", "image/gif"]
}
]
}
}
}
จากนั้นคุณต้องจัดการคำขอ POST
ขาเข้าในโปรแกรมทำงานของบริการ ระบบจะจัดเก็บไฟล์ไว้ในแคชสื่อชั่วคราวเพื่อให้ใช้งานได้ในไคลเอ็นต์ ซึ่งทำได้โดยการเปลี่ยนเส้นทางแอปไปยัง URL ที่มีพารามิเตอร์การค้นหาของเครื่องหมายพิเศษ เช่น share-target
self.addEventListener('fetch', (fetchEvent) => {
if (fetchEvent.request.url.endsWith('/receive-files/') && fetchEvent.request.method === 'POST') {
return fetchEvent.respondWith(
(async () => {
const formData = await fetchEvent.request.formData();
const image = formData.get('image');
const keys = await caches.keys();
const mediaCache = await caches.open(keys.filter((key) => key.startsWith('media'))[0]);
await mediaCache.put('shared-image', new Response(image));
return Response.redirect('./?share-target', 303);
})(),
);
}
});
สุดท้าย คุณต้องใช้ไฟล์ในไคลเอ็นต์
window.addEventListener('load', async () => {
if (location.search.includes('share-target')) {
const keys = await caches.keys();
const mediaCache = await caches.open(
keys.filter((key) => key.startsWith('media'))[0],
);
const image = await mediaCache.match('shared-image');
if (image) {
const blob = await image.blob();
await mediaCache.delete('shared-image');
// Handle the shared file somehow.
}
}
});
อ่านเพิ่มเติม
เดโม
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="manifest" href="manifest.json" />
<title>How to receive shared files</title>
<link rel="stylesheet" href="style.css" />
<!-- TODO: Devsite - Removed inline handlers -->
<!-- <script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', async () => {
const registration = await navigator.serviceWorker.register(
'sw.js',
);
console.log(
'Service worker registered for scope',
registration.scope,
);
});
}
</script>
<script src="script.js" type="module"></script> -->
</head>
<body>
<h1>How to receive shared files</h1>
<p>Install the app. After the installation, try sharing an image to it from another app.
</body>
</html>
CSS
html {
box-sizing: border-box;
font-family: system-ui, sans-serif;
color-scheme: dark light;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
margin: 1rem;
}
img {
height: auto;
max-width: 100%;
display: block;
}
JS
window.addEventListener('load', async () => {
if (location.search.includes('share-target')) {
const keys = await caches.keys();
const mediaCache = await caches.open(
keys.filter((key) => key.startsWith('media'))[0],
);
const image = await mediaCache.match('shared-image');
if (image) {
const blob = await image.blob();
await mediaCache.delete('shared-image');
// Handle the shared file somehow.
}
}
});