Introduction
Web Storage
WebSQL
IndexedDB
File System Access
Final Considerations
This presentation has been developed in the context of the Mobile Applications Development course, DISIM, University of L'Aquila (Italy), Spring 2014.
http://www.ivanomalavolta.com
3. Local storage and ļ¬le system access
There are 4 ways to store data locally in Cordova:
ā¢āÆ Web storage
ā¢āÆ Local Storage
ā¢āÆ Session Storage
ā¢āÆ WebSQL
ā¢āÆ Indexed DB
ā¢āÆ File System Access
Web storage, WebSQL, and
IndexedDB conform to W3C
speciļ¬cations and are provided
by the browser itself
File system access API conforms to its
corresponding W3C speciļ¬cation
4. Web Storage
LocalStorage
stores data in key/value pairs
persists across browser sessions
SessionStorage
stores data in key/value pairs
data is erased when a browser session ends
5. WebSQL
relational DB
support for tables creation, insert, update, ā¦
transactional
persists across browser sessions
Its evolution is called IndexedDB
6. WebSQL
It provides you a structured SQL relational database
You have to setup a DB schema
You can then perform classical SQL queries
tx.executeSql("SELECT
Ā *
Ā FROM
Ā Userā,
Ā [],
Ā
Ā
Ā
Ā function(tx,
Ā result)
Ā {
Ā
Ā
Ā
Ā
Ā //
Ā callback
Ā code
Ā
});
Ā
7. IndexedDB
ā¢āÆ It tries to combine Web Storage and WebSQL
ā¢āÆ You can save data as key/value pairs
ā¢āÆ You can deļ¬ne multiple DBs
ā¢āÆ Good Performance
āāÆ data is indexed
āāÆ Asynchronous Ć ļ it does not block the UI
You can see a store as a big SQL table with only key/value pairs
Ć ļ you donāt need to deļ¬ne a schema upfront
8. File System
ā¢āÆ you can access ļ¬les locally to your app
ā¢āÆ supports main FS operation
āāÆ creation, move, delete, rename, etc.
ā¢āÆ it is not transactional
ā¢āÆ persists across browser sessions
10. Web Storage
It is based on a single persistent object called
localStorage
You can set values by calling
window.localStorage.setItem(ānameā, āIvanoā);
You can get values back by calling
var name = window.localStorage.getItem(ānameā);
11. Supported Methods
.key(0)
Returns the name of the key at the position speciļ¬ed
.getItem(ākeyā)
Returns the item identiļ¬ed by it's key
.setItem(ākeyā, āvalueā)
Saves and item at the key provided
.removeItem(ākeyā)
Removes the item identiļ¬ed by it's key
.clear()
Removes all the key-value pairs
12. Complex Objects
Current implementations support only string-to-string mappings
Ć ļ āÆ you can store only strings
Ć ļ āÆ keys can be only strings
You can use JSON serialization if you need to store complex data
structures
13. Example of JSON Serialization
// simple class declaration
function Person(name, surname) {
this.name = name;
this.surname = surname;
}
// object creation
var user = new Person(āIvanoā, āMalavoltaā);
// object serialization
window.localStorage.setItem(āuserā, JSON.stringify(user));
// object retrieval
var current =
JSON.parse(window.localStorage.getItem(āuserā));
14. Checking Existence
You can simply check if the needed element is == null
if (window.localStorage.getItem(āuserā)) {
// there is an object in user
} else {
// the user key does not have any value
}
15. Selecting elements
In this case you have to manually iterate on elements
var users = [...]; // array of Person objects
window.localStorage.setItem(āusersā,
JSON.stringify(users));
var allUsers =
JSON.parse(window.localStorage.getItem(āusersā));
var ivanos = [];
for(var i=0; i<allUsers.length; i++) {
if(allUsers[i].name == āIvanoā)
ivanos.push(allUsers[i]);
}
16. Counting Elements
Also in this case, we have to do it manually
var usersNumber =
JSON.parse(window.localStorage.getItem(āusersā)).length;
17. Session Storage
Session Storage provides the same interface as Local Storage
Ć ļ you can call the same methods
but
Session Storage is cleared between app launches
19. WebSQL
It provides you a structured SQL relational database
You have to setup a DB schema
You can then perform classical SQL queries
tx.executeSql("SELECT * FROM Userā, [],
function(tx, result) {
// callback code
});
20. Opening a DB
Done via a dedicated function
var db =
openDatabase(āTest', ā1.0', āTest DB', 100000);
It creates a new SQLite DB and returns a new Database object
The Database object will be used to manipulate the data
21. Opening a DB: syntax
openDatabase(name, version, displayname, size);
name
the name of the DB
version
the version of the DB
displayname
the display name of the DB
size
the size of the DB in bytes
22. Database
It allows to manipulate the data via 2 methods:
changeVersion
atomically verify the version number and change it
db.changeVersion("1.0", "1.1");
transaction
performs a DB transaction
23. Transactions
It allow you to execute SQL statements against theĀ DB
db.transaction(queries, error, success);
3 functions as parameters:
queries : contains the queries to be performed
error : executed if the transaction results in an error
success : executed if the transaction terminates correctly
25. executeSql
It is the method that performs a SQL statement
The user can build up a database transaction by calling the
executeSql method multiple times
function populateDB(tx) {
tx.executeSql('DROP TABLE IF EXISTS USER');
tx.executeSql('CREATE TABLE IF NOT EXISTS USER (id
unique, name, surname)');
tx.executeSql('INSERT INTO USER(id, name, surname)
VALUES (1, ?, ?)ā, [āIvanoā, āMalavoltaā],
success, error);
}
26. Result Sets
When the executeSql method is called, it will invoke it's callback
with a SQLResultSet parameter
It has 3 properties:
insertId
the ID of the row that has been inserted
rowsAffected
the number of rows changed by the SQL statement
rows
the data returned from a SQL select statement
rows is an object of type SQLResultSetListĀ
27. Results Sets Example
...
tx.executeSql('INSERT INTO USER(id, name,surname) VALUES
(5, ?, ?)ā, [āIvanoā, āMalavoltaā], success, error);
}
function success(tx, results) {
var affected = results.rowsAffected(); // 1
}
function error(err) {
// code for managing the error
}
28. Result Set Lists
It contains the data returned from a SQL Select statement
length
the number of rows returned by the SQL query
Ā
item(index)
returns the row at the speciļ¬ed index represented by a JavaScript
object
29. Result Set List Example
...
tx.executeSql(āSELECT * FROM USERā, [], success, error);
}
function success(tx, results) {
var size = results.rows.length;
for (var i=0; i<size; i++){
console.log(results.rows.item(i).name);
}
}
30. Errors
It contains information about an occurred error
code
A predeļ¬ned error code
es.
UNKNOWN_ERR,
DATABASE_ERR,
TOO_LARGE_ERR,
QUOTA_ERR,
TIMEOUT_ERR,
SYNTAX_ERR
message
A description of the error
error not considered by any other error codes
internal error of the database
the result set is too large
the db now exceeds the storage space of the app
ā¢āÆ the statement is not sintactically correct
ā¢āÆ the number of parameters does not match with
placeholders
no reasonable time to get the lock for the transition
33. Indexed DB
It tries to combine Web Storage and WebSQL
You can save data as key/value pairs
You can deļ¬ne multiple DBs
Good Performance
data is indexed
asynchronous Ć ļ it does not block the UI
34. Indexed DB
An Indexed DB is a collection of object stores
You can drop objects into the stores
You can see a store as a big SQL table with only key/value pairs
Ć ļ you donāt need to deļ¬ne a schema upfront
37. File System Access
It allows you to read, write and navigate ļ¬le system hierarchies
It is fundamental for managing and storing large ļ¬les and binary
content on the client-side
38. File System Access Workļ¬ow
1.āÆ request ļ¬le system access
āāÆ persistent or temporary ļ¬le system
2.āÆ then you can perform CRUD operations for both ļ¬les and
folders:
āāÆ Create
āāÆ Read
āāÆ Update
āāÆ Delete
39. Request File System
requestFileSystem(type, size, successCb, [errorCb])
type
LocalFileSystem.TEMPORARY
LocalFileSystem .PERSISTENT
size
size in bytes the app will require for storage
successCb
success callback, its argument is a FileSystem object
ErrorCb
error callback, its argument is a FileError object
40. Temporary VS Persistent
Temporary
the ļ¬les stored by the app can be deleted at the browserās
discretionĀ
Ć ļ no guarantee of persistence
Persistent
cannot be deleted by the browser without authorization by the
app
41. Local File System Example
window.requestFileSystem(
LocalFileSystem.PERSISTENT,
0,
onSuccess,
onError);
function onSuccess(fileSystem) {
console.log(fileSystem.name);
}
leave it to zero, Apache Cordova will take care of it
42. File System
The FileSystem object has 2 properties:
name
the name of the ļ¬le system
it is unique across the list of exposed ļ¬le systems
root
the DirectoryEntry object representing the root folder of the
ļ¬le system
43. Resolving a File URI
resolveLocalFileSystemURI
retrieve a DirectoryEntryĀ or FileEntryĀ using a URI
window.resolveLocalFileSystemURI(
"file:///userImg.png", onSuccess, onError);
function onSuccess(fileEntry) {
console.log(fileEntry.name);
}
45. File Entry
It represents a ļ¬le on a ļ¬le system
isFile (boolean)
Always true
isDirectory (boolean)
Always false
name (DOMString)
the name of the FileEntry, excluding the pathĀ
fullPath (DOMString)
the full absolute path from the root
46. File Entry Methods
getMetadata(success, fail)
Look up metadata about a ļ¬le
setMetadata(success, fail, metadataObject)
Sets the metadata of the ļ¬le
moveTo(parentEntry, newName, success, fail)
Move a ļ¬le to a different location on the ļ¬le system
copyTo(parentEntry, newName, success, fail)
Copy a ļ¬le to a different location on the ļ¬le system
toURL()
Return a URL that can be used to locate a ļ¬le
47. File Entry Methods
remove(success, fail)
Delete a ļ¬le
getParent(success, fail)
Look up the parent directory
createWriter(success, fail)
Creates aĀ FileWriterĀ object that can be used to write to a ļ¬le
ļ¬le(success, fail)
Creates aĀ File object containing ļ¬le properties
48. File
It contains attributes of a single ļ¬le
name (DOMString)
The name of the ļ¬le
fullPath (DOMString)
The full path of the ļ¬le including the ļ¬le name
type (DOMString)
The mime type of the ļ¬leĀ
lastModiļ¬edDate (Date)
The last time the ļ¬le was modiļ¬ed
size (long) Ā
The size of the ļ¬le in bytes
50. Directory Entry Methods
getMetadata(success, fail)
Look up metadata about a directory
setMetadata(success, fail, metadataObject)
Sets the metadata of the directory
moveTo(parentEntry, newName, success, fail)
Move a directory to a different location on the ļ¬le system
copyTo(parentEntry, newName, success, fail)
Copy a directory to a different location on the ļ¬le system
toURL()
Return a URL that can be used to locate a directory
51. Directory Entry Methods
getParent(success, fail)
Look up the parent directory
createReader()
Creates aĀ DirectoryReader object that can be used to read a
directory
getDirectory(path, options, success, fail)
Creates or looks up a directory
options:
create: (true | false)
exclusive: (true | false)
52. Directory Entry Methods
getFile(path, options, success, fail)
Create or look up a ļ¬le within the directory
options:
create Ć ļ (true | false)
exclusive Ć ļ (true | false)
removeRecursively(success, fail)
Delete a directory and all of its contents
53. File Reader
It is used to read the contents of a ļ¬le
Files can be read as:
ā¢āÆ text
ā¢āÆ base64 data encoded string
ā¢āÆ binary string
ā¢āÆ array buffer
You can also abort() a ļ¬le reading activity
You can register your own event listeners to receive the
following events:
loadstart, progress, load, loadend, error, abort
54. File Reader Example
entry.file(win, fail);
function win(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log(evt.target.result);
};
reader.readAsText(file);
// reader.abort();
};
function fail(evt) {
console.log(error.code);
};
55. File Writer
It is used to write to a ļ¬le
The data to be written must be UTF-8 encoded
You can register your own event listeners to receive the
following events:
writestart, progress, write, writeend, error, abort
56. File Writer
AĀ FileWriter is created for a single ļ¬le
You can use it to write to a ļ¬le multiple times
Ć ļ āÆthe FileWriterĀ maintains the ļ¬le's position and length
attributes, so you can seek and write anywhere in the ļ¬le
By default, the FileWriter writes to the beginning of the ļ¬le (will
overwrite existing data)
Set the optional append boolean to true in theĀ FileWriter's
constructor to begin writing to the end of the ļ¬le
57. File Writer Methods
abort()
Aborts writing ļ¬le
seek(byte)
Moves the ļ¬le pointer to the byte speciļ¬ed.
truncate(length)
Shortens the ļ¬le to the length speciļ¬ed.
write(data)
Writes data to the ļ¬le
58. File Writer Example
entry.createWriter(win, fail);
function win(writer) {
writer.onwrite = function(evt) {
console.log(āok");
};
writer.write(āIvano Malavolta");
};
function fail(evt) {
// error management
};
59. Directory Reader
It is an object that lists ļ¬les and directories in a directory
It has only one method:
readEntries(success, fail)
Read the entries of the directory
60. Directory Reader Example
var directoryReader = dirEntry.createReader();
directoryReader.readEntries(success, fail);
function success(entries) {
var i;
for (i=0; i<entries.length; i++) {
console.log(entries[i].name);
}
}
function fail(error) {
console.log(error.code);
}
61. A Final Example
window.requestFileSystem(window.PERSISTENT, 0, initFS, error);
function initFS(fs) {
fs.root.getFile(ālog.txt', {}, win, error);
}
function win(fileEntry) {
fileEntry.file(read, error);
}
function read(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
console.log(this.result);
};
reader.readAsText(file);
}
function error(err) { console.log(err);}
Looking for a ļ¬le and reading it
62. File upload
Upload ļ¬les to a remote server via an HTTP multi-part POST
request
var fileURI; // the path of the file on the device
var server; // the URL of the server
var win; // success callback
var fail; // error callback
var options; // optional parameters (see next slide)
var trustAll; // optional boolean parameter, set it to
// true to accept all security certificates
var ft = new FileTransfer();
ft.upload(fileURI, encodeURI(server), win, fail, options);
63. File upload options
The FileUploadOptions can be used to specify additional
parameters to the upload script
var options = new FileUploadOptions();
options.fileKey="fileā;
options.fileName= āfileNameā);
options.mimeType="text/plain";
ā¦
64. File upload options
ļ¬leKey: the name of the form element
ļ¬leName: the ļ¬le name to use when saving the ļ¬le on the server
mimeType: the mime type of the data to upload. Defaults to
image/jpeg
params: a set of optional key/value pairs to pass in the HTTP
request
chunkedMode: whether to upload the data in chunked streaming
mode. Defaults to true
headers: a map of header name/header values
65. File upload result
A FileUploadResult object is passed to the success callback
Properties:
bytesSent: the number of bytes sent to the server
responseCode: The HTTP response code returned by the server
response: The HTTP response returned by the server as string
66. File download
Downloads ļ¬les from a remote server via an HTTP GET request
var source; // URL of the file to be downloaded
var target; // full path of the file to be saved
var win; // success callback (takes FileEntry object)
var fail; // error callback
var options; // optional parameters (only headers)
var trustAll; // optional boolean parameter, set it to
// true to accept all security certificates
var ft = new FileTransfer();
ft.download(encodeURI(source),target, win, fail, options);
67. File transfer abort
Used to stop an on-going ļ¬le transfer
var ft = new FileTransfer();
ft.upload(fileURI, encodeURI(server), win, fail, options);
// perform some operation
ft.abort():
68. File transfer progress
Special callback activated every time a new piece of data is
transferred
ft.onprogress = function(progress) {
if (progressEvent.lengthComputable) {
console.log((progress.loaded / progress.total) + ā%ā);
} else {
console.log(āprogressedā);
}
};
ft.download(...); // the same works for upload
69. File transfer error
The FileTransferError object stores information about an error
occurred during a ļ¬le transfer (either upload or download)
Properties:
code: predeļ¬ned error code
source: URI of the source
target: URI of the target
http_status: HTTP status code from the server (if received)
FileTransferError.FILE_NOT_FOUND_ERR
FileTransferError.INVALID_URL_ERR
FileTransferError.CONNECTION_ERR
FileTransferError.ABORT_ERR
71. Considerations
You will likely use more than one API in combination
Ć ļ Use the right API for the right job
Web Storage
ā¢āÆ it is not transactional Ć ļ race conditions
ā¢āÆ very simple API, no schema
ā¢āÆ only String data Ć ļ performance issues for complex data due
to JSON serialization
ā¢āÆ session storage will be cleared after the app is closed
ā¢āÆ limited quota
72. Considerations
WebSQL
SQL-based Ć ļ fast and efļ¬cient
transactional Ć ļ more robust
asynchronous Ć ļ does not block the UI
rigid data structure Ć ļ data integrity vs agility
limited quota
73. Considerations
IndexedDB
simple data model Ć ļ easy to use
transactional Ć ļ more robust
asynchronous Ć ļ does not block the UI
good search performance Ć ļ indexed data
data is unstructured Ć ļ integrity problems
limited quota
not supported by every platform (e.g., iOS)
74. Considerations
File System
asynchronous Ć ļ does not block the UI
not transactional
indexing and search are not built-in Ć ļ you have to implement
your lookup functions
unlimited quota Ć ļ useful for images, videos, documents, etc.
76. About quotas...
Local Storage
~ 10Mb
Session Storage
~ 10Mb
WebSQL
~ 50-80Mb (depends on
the device)
Indexed DB
~ 50-80Mb (depends on
the device)
File system
unlimited
Native DB
unlimited