Using HTML5/Javascript in Windows Store apps: Data access and storage mechanism (II)
Introduction
Windows Store app offers lots of methods for data access and storage. And this article will only focus on HTML5/JavaScript programming.
In this tutorial, we’ll go over Application Data, File API , HTML5 Web Storage, Indexed Database API and remote data access. With these you can store more data – and store it more efficiently.
Compare
Application Data:
Application data is mutable data that is specific to a particular app. It includes runtime state, user preferences, and other settings. Application data is created, read, updated, and deleted when the app is running. It is recommended that Windows Store apps use app data stores for settings and files that are specific to each app and user. The system manages the data stores for an app, ensuring that they are kept isolated from other apps and other users. The system also preserves the contents of these data stores when the user installs an update to your app and removes the contents of these data stores completely and cleanly when your app is uninstalled. More details, you could refer to: Accessing app data with the Windows Runtime.
File API:
Windows.ApplicationModel.Package.current.installedLocation
It is the folder where your app is installed on the user’s system. You could get the location of the installed package. And then read the file. For example, if there has a “app_data” folder in the project, and there also has a file “myfile.data”. You could read that as follow (note: there only has read authority)
// folder structure
var dataFile = "app_data\\myfile.data";
// Get the data file from the package's app_data directory
Windows.ApplicationModel.Package.current.installedLocation.getFileAsync(dataFile).then(
function (file) {
return Windows.Storage.FileIO.readTextAsync(file);
}).done(function (text) {
document.getElementById("content").innerHTML = text;
});
You may store some configuration file at here. And then read when using.
By the way, you are also retrieve a file directly from your app's install directory by using an app URI, like this:
var uri = new Windows.Foundation.Uri("ms-appx:///app_data/myfile.data")
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) {
return Windows.Storage.FileIO.readTextAsync(file);
}).done(function (text) {
document.getElementById("content").innerHTML = text;
});
Windows.Storage.ApplicationData.current.localFolder, roamingFolder and temporaryFolder
They are these folders where your app can store data. These folders (local, roaming and temporary) are created by Windows when your app is installed. There are two primary ways to access files and folders from your app’s data locations:
- Use ApplicationData properties to retrieve an app data folder.
For example, you can use ApplicationData.LocalFolder to retrieve a StorageFolder that represents your app's local folder like this:
//localFolder
var localFolder = Windows.Storage.ApplicationData.current.localFolder;
console.log(localFolder.path);
// C:\Users\user\AppData\Local\Packages\0d09571c-8a31-4fd3-a9ed-6234b87a77d9_dwbz818qp68jr\LocalState
If you want to access your app's roaming or temporary folder, use the RoamingFolder or TemporaryFolder property instead. The code as follow:
//RoamingFolder
var roamingFolder = Windows.Storage.ApplicationData.current.roamingFolder;
console.log(roamingFolder.path);
// C:\Users\user\AppData\Local\Packages\0d09571c-8a31-4fd3-a9ed-6234b87a77d9_dwbz818qp68jr\RoamingState
//TemporaryFolder
var temporaryFolder = Windows.Storage.ApplicationData.current.temporaryFolder;
console.log(temporaryFolder.path);
// C:\Users\user\AppData\Local\Packages\0d09571c-8a31-4fd3-a9ed-6234b87a77d9_dwbz818qp68jr\TempState
- 2. You can retrieve a file directly from your app's local folder by using an app URI, like this:
Windows.Storage.StorageFile.getFileFromApplicationUriAsync("ms-appdata:///local/file.txt").done(
function (file) {
// Process file
});
And also with RoamingFolder or TemporaryFolder as follow:
Windows.Storage.StorageFile.getFileFromApplicationUriAsync("ms-appdata:///roaming/file.txt").done(
function (file) {
// Process file
});
Windows.Storage.StorageFile.getFileFromApplicationUriAsync("ms-appdata:///temp/file.txt").done(
function (file) {
// Process file
});
- 3. You can create a file in these folders like follow:
Windows.Storage.ApplicationData.current.localFolder.createFileAsync("file.txt", Windows.Storage.CreationCollisionOption.replaceExisting)
.then(function (file) {
return Windows.Storage.FileIO.writeTextAsync(file, “Hello World!”);
});
Note: You can’t access the local, roaming, or temporary folders through the file picker.
Windows.Storage.DownloadsFolder
It is the folder where downloaded files are saved by default. It is like “C:\Users\user\Downloads\ProjectName”. By default, your app can only access files and folders in the user's Downloads folder that your app created. However, you can gain access to files and folders in the user's Downloads folder by calling a file picker (FileOpenPicker or FolderPicker) so that users can navigate and pick files or folders for your app to access.
You can create a file in the user's Downloads folder like this:
Windows.Storage.DownloadsFolder.createFileAsync("file.txt").done(
function (newFile) {
return Windows.Storage.FileIO.writeTextAsync(newFile, “Hello World!”);
});
Note: If you create a file or folder in the Downloads folder, we recommend that you add that item to your app's FutureAccessList so that your app can readily access that item in the future.
Windows.Storage.KnownFolders
In addition to the default locations, a Windows Store app can access more files and folders by declaring capabilities in the app manifest, or by calling a file picker to let the user pick files and folders for the app to access.
The following table lists additional locations that you can access by declaring a capability (or capabilities) and using the associated Windows.Storage API:
Location |
Capability |
Windows.Storage API |
Documents library |
DocumentsLibraryNote You must add File Type Associations to your app manifest that declare specific file types that your app can access in this location. |
KnownFolders.DocumentsLibrary |
Music library |
||
Pictures library |
||
Videos library |
||
Homegroup libraries |
At least one of the following capabilities is needed. |
|
Removable devices |
Note You must add File Type Associations to your app manifest that declare specific file types that your app can access in this location. |
|
Media server devices (DLNA) |
At least one of the following capabilities is needed. |
|
Universal Naming Convention (UNC) folders |
A combination of the following capabilities is needed.
Note You must add File Type Associations to your app manifest that declare specific file types that your app can access in this location. |
Retrieve a folder using: StorageFolder.GetFolderFromPathAsync Retrieve a file using: |
For example, you can create a file in the Documents library folder like this:
Windows.Storage.KnownFolders.documentsLibrary.createFileAsync("sample.dat", Windows.Storage.CreationCollisionOption.replaceExisting).done(
function (file) {
return Windows.Storage.FileIO.writeTextAsync(file, “Hello World!”);
},
// Handle errors with an error function
function (error) {
// Process errors
});
Html5 Web Storage and Indexed Database API
These are HTML5 specific feature. And this is also only supported by Windows Store app built with HTML/JavaScript (C#/VB.NET and C++ based app cannot benefit from this).
Web Storage stores key-value pairs on the client side. But can’t store a larger amount of data, recommends a limit of 5 MB. You can use that as follow:
localStorage["name"] = "roy";
var name = localStorage["name"];
console.log(name);
You could use it as same as normal html5 web develop. More details, please refer to: Introduction to Web Storage (Internet Explorer) .
Indexed Database, each app has a quota of 250MB. Among all apps on the device, the limit is 4% of the disk size or 20GB, whichever is smaller. For hard drives that are less than 30GB, the limit among all apps on the device is 375MB. Because of the overall quota among all apps, test your app to ensure it functions properly when it can store very little or even no data because other apps consume the overall quota. IndexedDB is primarily useful as a place to cache data from a web service for offline usage. You can use that as follow:
try {
var db = null;
var sName = "ADatabase";
var nVersion = 1.0;
if (window.indexedDB) {
var req = window.indexedDB.open(sName, nVersion);
req.onsuccess = function (evt) {
db = evt.target.result;
doSomething(db);
}
req.onerror = handleError(evt);
req.onblocked = handleBlock(evt);
req.onupgradeneeded = handleUpgrade(evt);
}
}
catch( ex ) {
handleException( ex );
}
And there has a simple demonstrates a common usage pattern for the IndexedDB.
Conclusion
To really understand when to use each storage option, let's look at an example app.
Note This example shows how an app could use every storage option. The example is for illustration only. Due to the memory overhead with loading the binaries associated with each storage option, we don't recommended using every storage option when some can be combined.
Consider a basic app that manages a user's contacts. The user can add, remove, and search contacts. For each contact, the user can specify basic info and attach one or more pictures.
Here's a list of which storage options to use for different types of data:
- Remembering the user's preferences
The app has preferences the user can change, such as the background color and font size. The app reads these preferences when it's launched and uses them to initialize its appearance. Because the preferences are an essential part of the app and don't change often, use local settings or web storage to store this info.
- Remembering the last contact the user viewed
The user navigates through different contacts and then switches away from the app. When the user returns later, the app displays the same contact. The last viewed contact changes often. Use the session state to store the last viewed contact.
- Storing contacts and basic info
The user wants to easily and quickly search through their contacts. Use IndexedDB to store contact info. IndexedDB is well suited for managing large amounts of data, and provides the quickest way to traverse the data.
- Storing images of a contact
Images of contacts can get large, so don't use session state or local settings. Instead, use either IndexedDB or local storage, which allow an app to serialize and retrieve binary data.