Chrome擴展開發之三——Chrome擴展中的數據本地存儲和下載


 

目錄:
 

 

如果你對GmailAssist感興趣,可以在chrome商店中搜索“Gmail助手”,或點擊這里直接訪問商店來安裝試用;
如果你對GmailAssist的源碼感興趣,可以在我的GitHub上查看它的源碼。


 

一、數據本地存儲常用的兩種方式

1. HTML5 的 localStorage

在第二篇中說過,chrome擴展中的腳本都可以調用H5的一切API,自然localStorage也不例外。而localStorage的兩種形式:sessionStorage 和 localStorage 分別可以看成臨時和永久存儲:后者永久留在硬盤上,除非你在程序里remove掉,或者手動去刪掉;而前者,對在chrome中而言,本地存的數據的生存時間就等於相應標簽的生存時間。(這基本上是二者的唯一區別)

localStorage 有 setItem, getItem, removeItem, key, clear 這5個方法。localStorage中都是以 key/value的形式來存儲數據的,存儲的數據類型都是字符串。並且是明文,沒有加密(所以用戶密碼啥的可不能存啊)

GmailAssist開發初期,OAuth2的認證一開始搞得我一頭霧水,好不容易大概懂了原理,又覺得自己很難很好地拿js實現一個認證的模塊。Chrome給擴展程序的API中雖然有OAuth2相關的接口,但感覺好像不是很好用(現在回過頭來看,只是自己當時理解有問題,另外當時偷懶了沒去好好找好好學google給的例子程序)。於是從網上找來了一個現成的輪子(就是這個),源碼和使用說明都很詳細,就直接拿來用了。現在有了對js語法的進一步理解,回頭看看已經能清晰理解這份源碼了。其中保存授權token等信息都是直接使用的 localStorage,查了查發現還是很簡單好用的。可以簡單理解為大號的cookie。(cookie允許4K,localStorage允許5M)。

可以通過 localStorage 的API們訪問數據,也可以直接像訪問js變量一樣訪問。下面是從網上摘抄的例子:

//可以像對象字面量那樣使用Web Storage:
      localStorage.fresh = “vfresh.org”;   //設置一個鍵值
      var a = localStorage.fresh;   //獲取鍵值
      delete localStorage['fresh'];  //刪除鍵值
//或者使用它的API:
      localStorage.setItem(“fresh”,“vfresh.org”); //設置一個鍵值
      localStorage.getItem(“fresh”); //獲取一個鍵值
      localStorage.key(0); //獲取指定下標的鍵的名稱(如同Array)
      localStorage.removeItem(“fresh”); //刪除一個鍵值
      localStorage.clear(); //清空storage

注意一點!雖然所以腳本都可以訪問 localStorage 接口,但訪問時仍然是基於當前的域的。也就是說 content script 們和 background script 是無法通過 localStorage 訪問到同一塊本地數據的!(前者域是當前瀏覽頁面站點,后者是擴展程序自己的域“chrome://extension-id/”,如下圖是localStorage 所存放的本地文件夾,從命名就可以看出這些文件對應的域不同)

localStorage文件夾

最后說一下,localStorage 既然是永久保存在本地的,那它在硬盤的什么位置呢?如果我想直接看里面存的值,該怎么看呢?

硬盤位置:C:\Users\your_Username\AppData\Local\Google\Chrome\User Data\Default\Local Storage 。里面一個個的文件可以用SQLite打開查看。更方便的一個途徑是直接在Chrome中查看和修改:

打開chrome –> 訪問chrome://extensions/ (或從瀏覽器的設置中,找到“擴展程序”)-> 點擊你要看的擴展程序相關信息里的“背景頁”-> 在 resource 中的localStorage 處即可查看,雙擊即可修改。(如下圖)

localStorage

 

2. Chrome.storage

GmailAssist中未涉及,就不舉例細說了,詳細內容可以看官方文檔。只談它和 localStorage 有什么異同:

同:

  • 可以認為 chrome.storage 本身就是對 localStorage 的一個封裝。所以顯然,后者的功能它都有。
  • 它存的也是明文。

異:(我直接摘抄了漢化的文檔

這一 API 為擴展程序的存儲需要而特別優化,它提供了與 localStorage API 相同的能力,但是具有如下幾個重要的區別:

  • 用戶數據可以通過 Chrome 瀏覽器的同步功能自動同步(使用 storage.sync)。
  • 您的擴展程序的內容腳本可以直接訪問用戶數據,而不需要后台頁面。
  • 即使使用分離式隱身行為,用戶的擴展程序設置也會保留。
  • 它是異步的,並且能夠進行大量的讀寫操作,因此比阻塞和串行化的 localStorage API 更快。
  • 用戶數據可以存儲為對象(localStorage API 以字符串方式存儲數據)。
  • 可以讀取管理員為擴展程序配置的企業策略(使用 storage.managed 和架構)。

3. 何時用哪個

分別說下這兩種方式的優勢劣勢,選擇就很顯然了。

localStorage:

優勢:可以像普通的js變量一樣使用,簡單方便。

劣勢:

  1. content script 無法和 background 共同訪問一個域的數據,只能通過第二篇中提過的 sendMessage 來交流數據;
  2. 不像chrome.storage 是用異步方式訪問數據,localStorage相對在訪問數據略多時會比 chrome.storage 慢;
  3. 隱身模式下無法訪問數據;
  4. 如果擴展程序的一些設置參數是用 localStorage 保存在本地的,用戶在其他計算機上無法獲得這份設置的同步備份,而chrome.storage通過 sync的設置就可以實現這種同步;
  5. 存儲數據都是字符串,若需要對象,還需要手動轉一下(雖然也不麻煩吧…)。

chrome.storage:

優勢:(就和上面的劣勢相對嘛)

  1. content script可以使用.storage 接口來訪問擴展程序的域的數據;
  2. 異步訪問,快;
  3. 隱身模式下仍可以訪問數據;
  4. 聯網並登陸chrome時,將自動同步 sync 域的數據;
  5. 可以直接存對象類型的數據。

劣勢:異步訪問導致需要回調函數來處理獲取的數據,不能像localStorage那樣直接像js變量一樣訪問。

4. 還有一種方式 Web SQL

這種我沒用過,不多提了。查過一些與它相關的東西,我的感覺是它至少對於開發 GmailAssist 這種本地存東西不多,而且沒有什么需要在本地執行復雜查詢的擴展程序而言,不合適。

二、下載

chrome 擴展程序要發起文件下載,必須通過chrome.downloads API 來完成。沒什么不好理解的地方,要用的話就好好看看文檔就都明白了。我嘗試寫寫也感覺寫不出啥,無非是拷貝。所以直接給出這個我認為已經寫得很清楚的電子書章節的鏈接吧。

結合GmailAssist 說一下,我的下載功能的實現。

需求是:希望用戶可以在附件列表中勾選想要下載的項目,進行批量下載。

實現是:通過一個表,每行給個復選框,然后把每個復選框對應的附件的下載地址(這個地址是通過gmail API獲取郵件信息中的partid來生成的,更具體的我會在說gmail API時提到)作為參數,來調用 chrome.downloads.download 方法。但 partid 是在content script中獲取的,下載地址自然地就在content script中拼出來了,然而 content script能調用的chrome.* API中很不幸地沒有包括 .downloads 。咋整?誰能調這個API就把下載的邏輯寫在誰那,然后通過 sendMessage 把 url 傳給它唄。

於是我的 background.js 中就有如下代碼:

chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
    if (message.url) {
        chrome.downloads.download({
            url: message.url,
            conflictAction: 'uniquify',
            saveAs: false
        });
    } else if (...) {
        ...//其他的必須在后台處理的邏輯
    }
});

當然前提是必須在 manifest.json 中聲明使用 download 接口的權限:

{
        ...
        "permissions": [
          "downloads"
        ],
        ...
}

然后在 content.js 中:

btnDownload.onclick = function () {
       var id2 = 0;//id2用於遍歷附件列表,找出誰被用戶選中了,需要下載
        for (id2 = 0; id2 < visibleRows.length; id2++) {
            var chebox = document.getElementById("checkbox_" + id2);
            if (chebox.checked == true) {
                var url = 'https://mail.google.com/mail/u/0/?ui=2&ik=undefined&view=att&th=' + visibleRows[id2].split('|-|')[6] + '&attid=0.' + vis                ibleRows[id2].split('|-|')[7] + '&disp=safe&zw';//這句就是在拼下載地址
                chrome.runtime.sendMessage({url: url}, function (response) {
                ...//這里可以針對返回的 response 做些操作,不過我這里不需要
                });
            }
        }
 };

這樣就完成了下載。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM