blob: ab2beb20b41f96a9274bd103f5569bead4061da3 [file] [log] [blame]
var exec = require('cordova/exec'),
FileError = require('cordova/plugin/FileError'),
ProgressEvent = require('cordova/plugin/ProgressEvent');
/**
* This class writes to the mobile device file system.
*
* For Android:
* The root directory is the root of the file system.
* To write to the SD card, the file name is "sdcard/my_file.txt"
*
* @constructor
* @param file {File} File object containing file properties
* @param append if true write to the end of the file, otherwise overwrite the file
*/
var FileWriter = function(file) {
this.fileName = "";
this.length = 0;
if (file) {
this.fileName = file.fullPath || file;
this.length = file.size || 0;
}
// default is to write at the beginning of the file
this.position = 0;
this.readyState = 0; // EMPTY
this.result = null;
// Error
this.error = null;
// Event handlers
this.onwritestart = null; // When writing starts
this.onprogress = null; // While writing the file, and reporting partial file data
this.onwrite = null; // When the write has successfully completed.
this.onwriteend = null; // When the request has completed (either in success or failure).
this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
this.onerror = null; // When the write has failed (see errors).
};
// States
FileWriter.INIT = 0;
FileWriter.WRITING = 1;
FileWriter.DONE = 2;
/**
* Abort writing file.
*/
FileWriter.prototype.abort = function() {
// check for invalid state
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// set error
this.error = new FileError(FileError.ABORT_ERR);
this.readyState = FileWriter.DONE;
// If abort callback
if (typeof this.onabort === "function") {
this.onabort(new ProgressEvent("abort", {"target":this}));
}
// If write end callback
if (typeof this.onwriteend === "function") {
this.onwriteend(new ProgressEvent("writeend", {"target":this}));
}
};
/**
* Writes data to the file
*
* @param text to be written
*/
FileWriter.prototype.write = function(text) {
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// WRITING state
this.readyState = FileWriter.WRITING;
var me = this;
// If onwritestart callback
if (typeof me.onwritestart === "function") {
me.onwritestart(new ProgressEvent("writestart", {"target":me}));
}
// Write file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// position always increases by bytes written because file would be extended
me.position += r;
// The length of the file is now where we are done writing.
me.length = me.position;
// DONE state
me.readyState = FileWriter.DONE;
// If onwrite callback
if (typeof me.onwrite === "function") {
me.onwrite(new ProgressEvent("write", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Save error
me.error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
}, "File", "write", [this.fileName, text, this.position]);
};
/**
* Moves the file pointer to the location specified.
*
* If the offset is a negative number the position of the file
* pointer is rewound. If the offset is greater than the file
* size the position is set to the end of the file.
*
* @param offset is the location to move the file pointer to.
*/
FileWriter.prototype.seek = function(offset) {
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
if (!offset && offset !== 0) {
return;
}
// See back from end of file.
if (offset < 0) {
this.position = Math.max(offset + this.length, 0);
}
// Offset is bigger then file size so set position
// to the end of the file.
else if (offset > this.length) {
this.position = this.length;
}
// Offset is between 0 and file size so set the position
// to start writing.
else {
this.position = offset;
}
};
/**
* Truncates the file to the size specified.
*
* @param size to chop the file at.
*/
FileWriter.prototype.truncate = function(size) {
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// WRITING state
this.readyState = FileWriter.WRITING;
var me = this;
// If onwritestart callback
if (typeof me.onwritestart === "function") {
me.onwritestart(new ProgressEvent("writestart", {"target":this}));
}
// Write file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Update the length of the file
me.length = r;
me.position = Math.min(me.position, r);
// If onwrite callback
if (typeof me.onwrite === "function") {
me.onwrite(new ProgressEvent("write", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Save error
me.error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
}, "File", "truncate", [this.fileName, size]);
};
module.exports = FileWriter;