非標準
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 能夠存取儲存區,就可在該儲存區中新增、取得、移除檔案。
新增檔案
透過 addNamed
或 add
函式,即可新增檔案。前者可在儲存檔案時,設定明確的名稱;而後者則可自動建立名稱。這 2 組函式均屬非同步函式,並將回傳 DOMRequest
物件以處理作業的 success
或 error
狀態。因為在實體層上讀/寫檔案極為緩慢,所以此作業特別重要。
這 2 組函式均以 Blob
作為其第一參數。此物件將於背景之下轉為檔案並儲存起來。當建立 Blob
物件時將強制給予其 type,而因為某些儲存區會因類型而有所限制,所以此
MIME 類型格外重要:
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 種方法可檢索檔案:使用檔案名稱,或依序存取檔案列表。
最簡單的方式,就是使用 get
與 getEditable
函式來檢索檔案。前者可提供File
物件,即如同唯讀檔案一樣;後者則提供 FileHandle
物件,可更新底層檔案 (Under-laying file)。這 2 組函式均屬非同步函式,並會回傳 DOMRequest
物件,以處理作業的 success
或 error
狀態。
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); }
另一個檔案檢索方式,就是透過 enumerate
與 enumerateEditable
函式瀏覽儲存區的內容。前者可提供 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 組選擇性參數至 enumerate
與 enumerateEditable
函式,即可限制結果的數量。
第一組參數可為字串,代表所要搜尋的子資料夾。
第二組參數則是具備 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
物件,以處理作業的 success
或 error
的狀態。
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
物件,以處理作業的 success
或 error
的狀態。
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
物件:
DeviceStorageChangeEvent.reason
將提供變更 (created 或 modified
或deleted
) 的理由。DeviceStorageChangeEvent.path
則針對受變更所影響的檔案,提供其完整的路徑。
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 |