MDN wants to talk to developers like you: https://qsurvey.mozilla.com/s3/8d22564490d8

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,