共用方式為


與其他應用程式分享內容

應用程式間分享內容因行動裝置而普及,因為操作檔案或複製內容不如桌面作業系統直觀。 例如,在手機上,透過簡訊分享圖片給朋友是很常見的做法。 但分享內容並不僅限於行動裝置;在 Windows 上也可以在不同應用程式間分享。

內容分享有兩個方向,這兩個方向都可以由 Progressive Web Apps (PWA) 處理:

方向 描述
共用內容 為了分享內容,PWA 會產生內容 (,例如文字、連結或檔案,) ,並將這些共享內容交接給作業系統。 作業系統讓使用者決定想使用哪個應用程式來接收該內容。
接收共享內容 為了接收內容,PWA 作為內容目標。 PWA 會被註冊為作業系統中的內容分享目標。

註冊為分享目標的 PWA 感覺原生整合進作業系統,對使用者更具吸引力。

共用內容

PWA 可以使用 Web Share API 來觸發顯示作業系統分享對話框。

網路分享僅適用於透過 HTTPS (提供的網站,這與 PWA) 的情況相同,且只能在使用者操作後被呼叫。

要分享連結、文字或檔案等內容,請使用 navigator.share 以下所示的功能。 函 navigator.share 數接受一個物件,該物件至少應具備以下一項性質:

  • title:這是共享內容的簡稱。
  • text:分享內容的較長描述。
  • url:將要分享的資源地址。
  • files:一組要分享的檔案陣列。
function shareSomeContent(title, text, url) {
  if (!navigator.share) {
    return;
  }

  navigator.share({title, text, url}).then(() => {
    console.log('The content was shared successfully');
  }).catch(error => {
    console.error('Error sharing the content', error);
  });
}

在上述程式碼中,我們首先檢查瀏覽器是否支援網頁分享,方法是測試 navigator.share 是否定義了 。 該 navigator.share 函式會回傳一個 Promise 物件,當共享成功時會解析,發生錯誤時則會被拒絕。

由於此處使用了承諾,上述程式碼可重寫為 async 函式,如下:

async function shareSomeContent(title, text, url) {
  if (!navigator.share) {
    return;
  }

  try {
    await navigator.share({title, text, url});
    console.log('The content was shared successfully');
  } catch (e) {
    console.error('Error sharing the content', e);
  }
}

在 Windows 上,上述程式碼會觸發分享對話框,讓使用者選擇應用程式來接收共享內容。 分享對話框如下所示:

Windows 上的分享對話框

一旦使用者選擇了接收共享內容的應用程式,該應用程式就能自行決定如何處理。 例如,電子郵件應用程式可能會將 作為 title 電子郵件主旨,並使用 電子郵件 text 主體。

檔案共享

這個 navigator.share 函式也接受 files 陣列來與其他應用程式分享檔案。

在分享檔案前,先測試瀏覽器是否支援檔案分享非常重要。 要檢查是否支援檔案分享,請使用 navigator.canShare 以下函式:

function shareSomeFiles(files) {
  if (navigator.canShare && navigator.canShare({files})) {
    console.log('Sharing files is supported');
  } else {
    console.error('Sharing files is not supported');
  }
}

files共享物件成員必須是物件陣列File。 了解更多關於 檔案介面的資訊。

建構 File 物件的一種方式是:

  1. 首先,使用 fetch API 來請求資源。
  2. 然後,利用回傳的回應建立新的 File

這種做法如下所示。

async function getImageFileFromURL(imageURL, title) {
  const response = await fetch(imageURL);
  const blob = await response.blob();
  return new File([blob], title, {type: blob.type});
}

在上述程式碼中:

  1. 這個 getImageFileFromURL 函式是透過使用 URL 來取得圖片。
  2. response.blob() 函式會將影像轉換成 BLOB) (二進位大型物件。
  3. 程式碼會利用 BLOB 來建立 File 一個物件。

內容分享示範

PWAmp 是一款示範 PWA,利用該 navigator.share 功能分享文字與連結。

要測試分享功能:

  1. PWAmp 看看。

  2. 在地址列右側,點擊 可用應用程式。安裝PWA (「應用程式可用,安裝」圖示) 按鈕,即可將 PWAmp 安裝為 PWA。

  3. 在安裝的 PWAmp PWA 中,將本地音訊檔案 (拖曳到 App 視窗) 。 舉例來說,如果你複製了 MicrosoftEdge / Demos 倉庫,你就會在 /pwamp/songs/ 目錄中本地備份.mp3檔案,例如 C:\Users\localAccount\GitHub\Demos\pwamp\songs\

  4. 在新匯入的歌曲旁邊,點擊歌曲 動作 (......) 按鈕,然後選擇 分享。 顯示 Windows 分享 對話框:

    Windows 分享對話框,用來選擇哪個應用程式接收共享內容

  5. 選擇一個應用程式來分享內容。

你可以在 GitHub 找到 PWAmp 的原始碼 。 PWAmp 應用程式在 app.js 原始碼檔案中使用了 Web Share API。

接收共享內容

透過使用 Web Share Target API,PWA 可以註冊,以便在系統分享對話框中顯示為應用程式。 PWA 接著可以使用 Web Share Target API 來處理來自其他應用程式的共享內容。

只有已安裝的 PWA 才能註冊為共享目標。

註冊為目標

要接收共享內容,第一步是將您的 PWA 註冊為分享目標。 要註冊,請使用名單成員。share_target 安裝應用程式後,作業系統會利用該 share_target 成員將你的應用程式納入系統分享對話框中。 作業系統知道當你的應用程式被使用者選擇時該怎麼做,分享內容。

share_target會員必須包含系統將共享內容傳遞給你的應用程式所需的資訊。 請考慮以下清單代碼:

{
    "share_target": {
        "action": "/handle-shared-content/",
        "method": "GET",
        "params": {
            "title": "title",
            "text": "text",
            "url": "url",
        }
    }
}

當使用者選擇你的應用程式作為分享內容的目標時,PWA 就會啟動。 GET HTTP 請求會對該屬性所action指定的 URL 發出。 共享資料會以 titletext、 和 url 查詢參數的形式傳遞。 提出以下請求: /handle-shared-content/?title=shared title&text=shared text&url=shared url

如果你已有使用其他查詢參數名稱的程式碼,你可以將預設 title的 、 texturl 查詢參數映射到其他名稱。 在以下範例中,title、、 和 url 查詢參數被映射到 subjectbodyaddress和 : text

{
    "share_target": {
        "action": "/handle-shared-content/",
        "method": "GET",
        "params": {
            "title": "subject",
            "text": "body",
            "url": "address",
        }
    }
}

處理 GET 共享資料

要處理 GET 請求中共享的資料,請使用 URL 建構子擷取查詢參數:

window.addEventListener('DOMContentLoaded', () => {
    console url = new URL(window.location);

    const sharedTitle = url.searchParams.get('title');
    const sharedText = url.searchParams.get('text');
    const sharedUrl = url.searchParams.get('url');
});

處理 POST 共享資料

如果共享資料是要以任何方式改變你的應用程式,例如更新應用程式中儲存的內容,你必須使用該POST方法並定義編碼類型,為:enctype

{
    "share_target": {
        "action": "/post-shared-content",
        "method": "POST",
        "enctype": "multipart/form-data",
        "params": {
            "title": "title",
            "text": "text",
            "url": "url",
        }
    }
}

POST HTTP 請求包含共享資料,編碼為 multipart/form-data。 你可以用伺服器端程式碼存取 HTTP 伺服器上的這些資料,但當使用者離線時,這方法無法運作。 為了提供更好的體驗,請使用服務工作者,並透過 fetch 事件監聽器存取服務工作者的資料,具體如下:

self.addEventListener('fetch', event => {
    const url = new URL(event.request.url);

    if (event.request.method === 'POST' && url.pathname === '/post-shared-content') {
        event.respondWith((async () => {
            const data = await event.request.formData();

            const title = data.get('title');
            const text = data.get('text');
            const url = data.get('url');

            // Do something with the shared data here.

            return Response.redirect('/content-shared-success', 303);
        })());
    }
});

在上述程式碼中:

  1. 服務人員攔截了這個 POST 請求。

  2. 以某種方式使用資料 (例如將內容儲存在本地) 。

  3. 將使用者導向成功頁面。 這樣即使網路斷線,應用程式也能正常運作。 應用程式可以選擇只在本地儲存內容,或在連線恢復 ((例如使用背景同步) )後,將內容傳送到伺服器。

另請參閱:

處理共享檔案

應用程式也能處理共享檔案。 要處理 PWA 中的檔案,必須使用 POST 該方法和 multipart/form-data 編碼類型。 此外,你必須說明你的應用程式能處理哪些類型的檔案。

{
    "share_target": {
        "action": "/store-code-snippet",
        "method": "POST",
        "enctype": "multipart/form-data",
        "params": {
            "title": "title",
            "files": [
                {
                    "name": "textFile",
                    "accept": ["text/plain", "text/html", "text/css", 
                               "text/javascript"]
                }
            ]
        }
    }
}

上述清單程式碼告訴系統,你的應用程式可以接受各種 MIME 類型的文字檔。 也可以在陣列中傳遞accept檔案副檔名,例如 .txt

要存取共享檔案,請像之前一樣使用請求 formData 並使用 a FileReader 讀取內容,如下:

self.addEventListener('fetch', event => {
    const url = new URL(event.request.url);

    if (event.request.method === 'POST' && url.pathname === '/store-code-snippet') {
        event.respondWith((async () => {
            const data = await event.request.formData();

            const filename = data.get('title');
            const file = data.get('textFile');

            const reader = new FileReader();
            reader.onload = function(e) {
                const textContent = e.target.result;

                // Do something with the textContent here.

            };
            reader.readAsText(file);

            return Response.redirect('/snippet-stored-success', 303);
        })());
    }
});

另請參閱

MDN:

W3C:

PWAmp 示範: