arnaucube
arnaucube/openEventsPlatformAppPublic Self-hosted repository
openEventsPlatformApp/plugins/cordova-plugin-file/www/FileWriter.js
plugins/cordova-plugin-file/www/FileWriter.jsRaw
  1/*
  2 *
  3 * Licensed to the Apache Software Foundation (ASF) under one
  4 * or more contributor license agreements.  See the NOTICE file
  5 * distributed with this work for additional information
  6 * regarding copyright ownership.  The ASF licenses this file
  7 * to you under the Apache License, Version 2.0 (the
  8 * "License"); you may not use this file except in compliance
  9 * with the License.  You may obtain a copy of the License at
 10 *
 11 *   http://www.apache.org/licenses/LICENSE-2.0
 12 *
 13 * Unless required by applicable law or agreed to in writing,
 14 * software distributed under the License is distributed on an
 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 16 * KIND, either express or implied.  See the License for the
 17 * specific language governing permissions and limitations
 18 * under the License.
 19 *
 20*/
 21
 22var exec = require('cordova/exec'),
 23    FileError = require('./FileError'),
 24    ProgressEvent = require('./ProgressEvent');
 25
 26/**
 27 * This class writes to the mobile device file system.
 28 *
 29 * For Android:
 30 *      The root directory is the root of the file system.
 31 *      To write to the SD card, the file name is "sdcard/my_file.txt"
 32 *
 33 * @constructor
 34 * @param file {File} File object containing file properties
 35 * @param append if true write to the end of the file, otherwise overwrite the file
 36 */
 37var FileWriter = function(file) {
 38    this.fileName = "";
 39    this.length = 0;
 40    if (file) {
 41        this.localURL = file.localURL || file;
 42        this.length = file.size || 0;
 43    }
 44    // default is to write at the beginning of the file
 45    this.position = 0;
 46
 47    this.readyState = 0; // EMPTY
 48
 49    this.result = null;
 50
 51    // Error
 52    this.error = null;
 53
 54    // Event handlers
 55    this.onwritestart = null;   // When writing starts
 56    this.onprogress = null;     // While writing the file, and reporting partial file data
 57    this.onwrite = null;        // When the write has successfully completed.
 58    this.onwriteend = null;     // When the request has completed (either in success or failure).
 59    this.onabort = null;        // When the write has been aborted. For instance, by invoking the abort() method.
 60    this.onerror = null;        // When the write has failed (see errors).
 61};
 62
 63// States
 64FileWriter.INIT = 0;
 65FileWriter.WRITING = 1;
 66FileWriter.DONE = 2;
 67
 68/**
 69 * Abort writing file.
 70 */
 71FileWriter.prototype.abort = function() {
 72    // check for invalid state
 73    if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
 74        throw new FileError(FileError.INVALID_STATE_ERR);
 75    }
 76
 77    // set error
 78    this.error = new FileError(FileError.ABORT_ERR);
 79
 80    this.readyState = FileWriter.DONE;
 81
 82    // If abort callback
 83    if (typeof this.onabort === "function") {
 84        this.onabort(new ProgressEvent("abort", {"target":this}));
 85    }
 86
 87    // If write end callback
 88    if (typeof this.onwriteend === "function") {
 89        this.onwriteend(new ProgressEvent("writeend", {"target":this}));
 90    }
 91};
 92
 93/**
 94 * Writes data to the file
 95 *
 96 * @param data text or blob to be written
 97 * @param isPendingBlobReadResult {Boolean} true if the data is the pending blob read operation result
 98 */
 99FileWriter.prototype.write = function(data, isPendingBlobReadResult) {
100
101    var that=this;
102    var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
103    var isProxySupportBlobNatively = (cordova.platformId === "windows8" || cordova.platformId === "windows");
104    var isBinary;
105
106    // Check to see if the incoming data is a blob
107    if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
108        var fileReader = new FileReader();
109        fileReader.onload = function() {
110            // Call this method again, with the arraybuffer as argument
111            FileWriter.prototype.write.call(that, this.result, true /* isPendingBlobReadResult */);
112        };
113        fileReader.onerror = function () {
114            // DONE state
115            that.readyState = FileWriter.DONE;
116
117            // Save error
118            that.error = this.error;
119
120            // If onerror callback
121            if (typeof that.onerror === "function") {
122                that.onerror(new ProgressEvent("error", {"target":that}));
123            }
124
125            // If onwriteend callback
126            if (typeof that.onwriteend === "function") {
127                that.onwriteend(new ProgressEvent("writeend", {"target":that}));
128            }
129        };
130
131        // WRITING state
132        this.readyState = FileWriter.WRITING;
133
134        if (supportsBinary) {
135            fileReader.readAsArrayBuffer(data);
136        } else {
137            fileReader.readAsText(data);
138        }
139        return;
140    }
141
142    // Mark data type for safer transport over the binary bridge
143    isBinary = supportsBinary && (data instanceof ArrayBuffer);
144    if (isBinary && cordova.platformId === "windowsphone") {
145        // create a plain array, using the keys from the Uint8Array view so that we can serialize it
146        data = Array.apply(null, new Uint8Array(data));
147    }
148    
149    // Throw an exception if we are already writing a file
150    if (this.readyState === FileWriter.WRITING && !isPendingBlobReadResult) {
151        throw new FileError(FileError.INVALID_STATE_ERR);
152    }
153
154    // WRITING state
155    this.readyState = FileWriter.WRITING;
156
157    var me = this;
158
159    // If onwritestart callback
160    if (typeof me.onwritestart === "function") {
161        me.onwritestart(new ProgressEvent("writestart", {"target":me}));
162    }
163
164    // Write file
165    exec(
166        // Success callback
167        function(r) {
168            // If DONE (cancelled), then don't do anything
169            if (me.readyState === FileWriter.DONE) {
170                return;
171            }
172
173            // position always increases by bytes written because file would be extended
174            me.position += r;
175            // The length of the file is now where we are done writing.
176
177            me.length = me.position;
178
179            // DONE state
180            me.readyState = FileWriter.DONE;
181
182            // If onwrite callback
183            if (typeof me.onwrite === "function") {
184                me.onwrite(new ProgressEvent("write", {"target":me}));
185            }
186
187            // If onwriteend callback
188            if (typeof me.onwriteend === "function") {
189                me.onwriteend(new ProgressEvent("writeend", {"target":me}));
190            }
191        },
192        // Error callback
193        function(e) {
194            // If DONE (cancelled), then don't do anything
195            if (me.readyState === FileWriter.DONE) {
196                return;
197            }
198
199            // DONE state
200            me.readyState = FileWriter.DONE;
201
202            // Save error
203            me.error = new FileError(e);
204
205            // If onerror callback
206            if (typeof me.onerror === "function") {
207                me.onerror(new ProgressEvent("error", {"target":me}));
208            }
209
210            // If onwriteend callback
211            if (typeof me.onwriteend === "function") {
212                me.onwriteend(new ProgressEvent("writeend", {"target":me}));
213            }
214        }, "File", "write", [this.localURL, data, this.position, isBinary]);
215};
216
217/**
218 * Moves the file pointer to the location specified.
219 *
220 * If the offset is a negative number the position of the file
221 * pointer is rewound.  If the offset is greater than the file
222 * size the position is set to the end of the file.
223 *
224 * @param offset is the location to move the file pointer to.
225 */
226FileWriter.prototype.seek = function(offset) {
227    // Throw an exception if we are already writing a file
228    if (this.readyState === FileWriter.WRITING) {
229        throw new FileError(FileError.INVALID_STATE_ERR);
230    }
231
232    if (!offset && offset !== 0) {
233        return;
234    }
235
236    // See back from end of file.
237    if (offset < 0) {
238        this.position = Math.max(offset + this.length, 0);
239    }
240    // Offset is bigger than file size so set position
241    // to the end of the file.
242    else if (offset > this.length) {
243        this.position = this.length;
244    }
245    // Offset is between 0 and file size so set the position
246    // to start writing.
247    else {
248        this.position = offset;
249    }
250};
251
252/**
253 * Truncates the file to the size specified.
254 *
255 * @param size to chop the file at.
256 */
257FileWriter.prototype.truncate = function(size) {
258    // Throw an exception if we are already writing a file
259    if (this.readyState === FileWriter.WRITING) {
260        throw new FileError(FileError.INVALID_STATE_ERR);
261    }
262
263    // WRITING state
264    this.readyState = FileWriter.WRITING;
265
266    var me = this;
267
268    // If onwritestart callback
269    if (typeof me.onwritestart === "function") {
270        me.onwritestart(new ProgressEvent("writestart", {"target":this}));
271    }
272
273    // Write file
274    exec(
275        // Success callback
276        function(r) {
277            // If DONE (cancelled), then don't do anything
278            if (me.readyState === FileWriter.DONE) {
279                return;
280            }
281
282            // DONE state
283            me.readyState = FileWriter.DONE;
284
285            // Update the length of the file
286            me.length = r;
287            me.position = Math.min(me.position, r);
288
289            // If onwrite callback
290            if (typeof me.onwrite === "function") {
291                me.onwrite(new ProgressEvent("write", {"target":me}));
292            }
293
294            // If onwriteend callback
295            if (typeof me.onwriteend === "function") {
296                me.onwriteend(new ProgressEvent("writeend", {"target":me}));
297            }
298        },
299        // Error callback
300        function(e) {
301            // If DONE (cancelled), then don't do anything
302            if (me.readyState === FileWriter.DONE) {
303                return;
304            }
305
306            // DONE state
307            me.readyState = FileWriter.DONE;
308
309            // Save error
310            me.error = new FileError(e);
311
312            // If onerror callback
313            if (typeof me.onerror === "function") {
314                me.onerror(new ProgressEvent("error", {"target":me}));
315            }
316
317            // If onwriteend callback
318            if (typeof me.onwriteend === "function") {
319                me.onwriteend(new ProgressEvent("writeend", {"target":me}));
320            }
321        }, "File", "truncate", [this.localURL, size]);
322};
323
324module.exports = FileWriter;