Device Storage API

非標準

This API is available on Firefox OS for privileged or certified applications only.

摘要

Device Storage API 可存取 Web Apps 中的檔案系統。存取檔案系統可能牽涉極高的安全敏感度,所以此 API 僅可用於 Privileged Apps。

注意:若裝置儲存媒體的存取速度極慢,可能是受限於實體層 (Physical level) 的關係。在許多情況下,若以 IndexedDB 資料庫儲存檔案,取代實體的裝置儲存媒體,將可達到更高的速度。

存取儲存媒體

進入點

若使用 navigator.getDeviceStorage() 函式,則可存取儲存區。此函式所接受的字串參數,可代表所要存取的儲存媒體名稱。函式回傳的 DeviceStorage 物件,可存取相關的儲存區。

Firefox OS 提供下列儲存名稱:

  • apps:此儲存範圍可用以儲存 Apps 所需的使用者資料。因為這些屬於重要資料,所以若要存取此儲存,將需要額外的授權,且僅限 Certified Apps。
  • music:音樂與音訊檔案的儲存區。
  • pictures:圖片檔案的儲存區。
  • sdcard:裝置的 SD 記憶卡儲存區。
  • videos:視訊檔案的儲存區。
var pics = navigator.getDeviceStorage('pictures');

為了要能使用所有儲存區,Apps 必須在自己的 manifest 檔案中載明這些儲存區。舉例來說,如果 Apps 要存取 sdcard 儲存區,則其 manifest 檔案中必須具備「device-storage:sdcard」的授權。

"permissions": {
  "device-storage:videos":{ "access": "readonly" },
  "device-storage:pictures":{ "access": "readwrite" }
}

使用儲存媒體

只要 Apps 能夠存取儲存區,就可在該儲存區中新增、取得、移除檔案。

新增檔案

透過 addNamedadd 函式,即可新增檔案。前者可在儲存檔案時,設定明確的名稱;而後者則可自動建立名稱。這 2 組函式均屬非同步函式,並將回傳 DOMRequest 物件以處理作業的 successerror 狀態。因為在實體層上讀/寫檔案極為緩慢,所以此作業特別重要。

這 2 組函式均以 Blob 作為其第一參數。此物件將於背景之下轉為檔案並儲存起來。當建立 Blob 物件時將強制給予其 type,而因為某些儲存區會因類型而有所限制,所以此 MIME 類型格外重要:

  • music 僅接受「具備有效音訊 MIME 類型」的 Blob
  • pictures 僅接受「具備有效圖像 MIME 類型」的 Blob
  • videos 僅接受「具備有效視訊 MIME 類型」的 Blob
var sdcard = navigator.getDeviceStorage("sdcard");
var file   = new Blob(["This is a text file."], {type: "text/plain"});

var request = sdcard.addNamed(file, "my-file.txt");

request.onsuccess = function () {
  var name = this.result;
  console.log('File "' + name + '" successfully wrote on the sdcard storage area');
}

// An error typically occur if a file with the same name already exist
request.onerror = function () {
  console.warn('Unable to write the file: ' + this.error);
}

注意:儲存區中的 Repository (Repo) 屬於隱性 (Implicit),因此不能建立顯性 (Explicit) 的空白 Repo。如果要使用 Repo 的結構,則必須針對 Repo 的名稱,使之成為儲存檔案名稱的一部分。所以,如果你要在 foo 庫中儲存 bar 檔案,就必須使用 addNamed 函式再搭配 addNamed(blob, "foo/bar") 檔案的完整路徑名稱。一旦要使用這個名稱檢索檔案,也可使用同樣的方式 (參閱下列)。

基於安全理由,如果檔案新增於既定的受限儲存區內,則檔案路徑名稱不能以「/」或「../」開頭 (且「./」為無意義)。

取得檔案

現有 2 種方法可檢索檔案:使用檔案名稱,或依序存取檔案列表。

最簡單的方式,就是使用 getgetEditable 函式來檢索檔案。前者可提供File 物件,即如同唯讀檔案一樣;後者則提供 FileHandle 物件,可更新底層檔案 (Under-laying file)。這 2 組函式均屬非同步函式,並會回傳 DOMRequest 物件,以處理作業的 successerror 狀態。

var sdcard = navigator.getDeviceStorage('sdcard');

var request = sdcard.get("my-file.txt");

request.onsuccess = function () {
  var file = this.result;
  console.log("Get the file: " + file.name);
}

request.onerror = function () {
  console.warn("Unable to get the file: " + this.error);
}

另一個檔案檢索方式,就是透過 enumerateenumerateEditable 函式瀏覽儲存區的內容。前者可提供 File 物件;後者則提供 FileHandle 物件。此 2 組均為非同步函式,並可回傳 DOMCursor 物件以依序存取檔案列表。DOMCursor 其實就是 DOMRequest,但又額外具備「非同步依序存取列表 (這裡則指檔案列表)」的功能。

var pics = navigator.getDeviceStorage('pictures');

// Let's browse all the images available
var cursor = pics.enumerate();

cursor.onsuccess = function () {
  var file = this.result;
  console.log("File found: " + file.name);

  // Once we found a file we check if there is other results
  if (!this.done) {
    // Then we move to the next result, which call the cursor
    // success with the next file as result.
    this.continue();
  }
}

cursor.onerror = function () {
  console.warn("No file found: " + this.error);
}

只要傳送 2 組選擇性參數至 enumerateenumerateEditable 函式,即可限制結果的數量。

第一組參數可為字串,代表所要搜尋的子資料夾。

第二組參數則是具備 since 屬性的物件,可限制在既定期間內搜尋。

var pics = navigator.getDeviceStorage('pictures');

// Lets retrieve picture from the last week.
var param = {
  since: new Date((+new Date()) - 7*24*60*60*1000)
}

var cursor = pics.enumerate(param);

cursor.onsuccess = function () {
  var file = this.result;
  console.log("Picture taken on: " + file.lastModifiedDate);

  if (!this.done) {
    this.continue();
  }
}

刪除檔案

透過 delete 函式,即可從儲存區移除檔案。此函式僅需所要刪除的檔案名稱。如同來自於 DeviceStorage 介面的其他所有函式,此函式亦屬於非同步 API,並會回傳 DOMRequest 物件,以處理作業的 successerror 的狀態。

var sdcard = navigator.getDeviceStorage('sdcard');

var request = sdcard.delete("my-file.txt");

request.onsuccess = function () {
  console.log("File deleted");
}

request.onerror = function () {
  console.log("Unable to delete the file: " + this.error);
}

儲存資訊

除了存取檔案之外,儲存區亦提供數個函式,可輕鬆取得某些重要資訊。

可用空間

在儲存檔案時,必須先了解的要素之一就是可用空間。DeviceStorage 介面則針對空間而提供 2 組有用函式:

  • freeSpace() 可取得「儲存新檔案」的空間容量
  • usedSpace() 可取得「已儲存檔案」的空間容量

這些函式亦屬於非同步 APIs,並會回傳 DOMRequest 物件,以處理作業的 successerror 的狀態。

var videos = navigator.getDeviceStorage('videos');

var request = videos.usedSpace();

request.onsuccess = function () {
  // The result is express in bytes, lets turn it into megabytes
  var size = this.result / 1000000;

  console.log("The videos on your device use a total of " + size.toFixed(2) + "Mo of space.");
}

request.onerror = function () {
  console.warn("Unable to get the space used by videos: " + this.error);
}

監聽變動狀態

可能有許多 Apps 同時存取相同的儲存區。如果 Apps 能知道儲存區中的變化,則可避免不必要的錯誤。又若 Apps 不依賴 DeviceStorage 介面的函式所回傳的 DOMRequest 物件,卻需執行非同步作業,那得知儲存區的變化亦頗有助益。

因為如此,只要建立、修改、刪除了某個檔案,就會觸發 change 事件。而透過 onchange 屬性或 addEventListener() 函式,即可取得這個事件。而事件處理器 (Event Handler) 所取得的 DeviceStorageChangeEvent 物件,則是擁有額外 2 組屬性的常態 Event 物件:

var sdcard = navigator.getDeviceStorage('sdcard');

sdcard.onchange = function (change) {
  var reason = change.reason;
  var path   = change.path;

  console.log('The file "' + path + '" has been ' + reason);
}

規格

目前尚無規格。

瀏覽器相容性

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support ? ? Not supported Not supported Not supported
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support ? ? Not supported Not supported Not supported

另可參閱

文件標籤與貢獻者

 此頁面的貢獻者: MashKao
 最近更新: MashKao,