diff --git a/doc/index.md b/doc/index.md index 997d273..2c12210 100644 --- a/doc/index.md +++ b/doc/index.md @@ -30,12 +30,15 @@ This plugin allows you to upload and download files. - Amazon Fire OS - Android - BlackBerry 10 +- Firefox OS** - iOS - Windows Phone 7 and 8* - Windows 8* \* _Do not support `onprogress` nor `abort()`_ +\** _Do not support `onprogress`_ + # FileTransfer The `FileTransfer` object provides a way to upload files using an HTTP diff --git a/plugin.xml b/plugin.xml index a0e585e..31dcb21 100644 --- a/plugin.xml +++ b/plugin.xml @@ -144,4 +144,14 @@ + + + + + + + + + + diff --git a/www/firefoxos/FileTransferProxy.js b/www/firefoxos/FileTransferProxy.js new file mode 100644 index 0000000..305ac58 --- /dev/null +++ b/www/firefoxos/FileTransferProxy.js @@ -0,0 +1,223 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +var cordova = require('cordova'), + FileTransferError = require('./FileTransferError'), + xhr = {}; + +function getParentPath(filePath) { + var pos = filePath.lastIndexOf('/'); + return filePath.substring(0, pos + 1); +} + +function getFileName(filePath) { + var pos = filePath.lastIndexOf('/'); + return filePath.substring(pos + 1); +} + +module.exports = { + abort: function (successCallback, errorCallback, args) { + var id = args[0]; + if (xhr[id]) { + xhr[id].abort(); + if (typeof(successCallback) === 'function') { + successCallback(); + } + } else if (typeof(errorCallback) === 'function') { + errorCallback(); + } + }, + + upload: function(successCallback, errorCallback, args) { + var filePath = args[0], + server = args[1], + fileKey = args[9], + fileName = args[3], + mimeType = args[4], + params = args[5], + /*trustAllHosts = args[6],*/ + /*chunkedMode = args[7],*/ + headers = args[8]; + + xhr[fileKey] = new XMLHttpRequest({mozSystem: true}); + xhr[fileKey].onabort = function() { + onFail(new FileTransferError(FileTransferError.ABORT_ERR, server, filePath, this.status, xhr[fileKey].response)); + }; + + window.resolveLocalFileSystemURL(filePath, function(entry) { + entry.file(function(file) { + var reader = new FileReader(); + + reader.onloadend = function() { + var blob = new Blob([this.result], {type: mimeType}); + var fd = new FormData(); + + fd.append(fileKey, blob, fileName); + + for (var prop in params) { + if (params.hasOwnProperty(prop)) { + fd.append(prop, params[prop]); + } + } + + xhr[fileKey].open("POST", server); + + xhr[fileKey].onload = function(evt) { + if (xhr[fileKey].status === 200) { + var result = new FileUploadResult(); + result.bytesSent = blob.size; + result.responseCode = xhr[fileKey].status; + result.response = xhr[fileKey].response; + delete xhr[fileKey]; + onSuccess(result); + } else if (xhr[fileKey].status === 404) { + onFail(new FileTransferError(FileTransferError.INVALID_URL_ERR, server, filePath, xhr[fileKey].status, xhr[fileKey].response)); + } else { + onFail(new FileTransferError(FileTransferError.CONNECTION_ERR, server, filePath, xhr[fileKey].status, xhr[fileKey].response)); + } + }; + + xhr[fileKey].ontimeout = function() { + onFail(new FileTransferError(FileTransferError.CONNECTION_ERR, server, filePath, xhr[fileKey].status, xhr[fileKey].response)); + }; + + xhr[fileKey].onerror = function() { + onFail(new FileTransferError(FileTransferError.CONNECTION_ERR, server, filePath, this.status, xhr[fileKey].response)); + }; + + for (var header in headers) { + if (headers.hasOwnProperty(header)) { + xhr[fileKey].setRequestHeader(header, headers[header]); + } + } + + xhr[fileKey].send(fd); + }; + + reader.readAsArrayBuffer(file); + + }, function() { + onFail(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR, server, filePath)); + }); + }, function() { + onFail(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR, server, filePath)); + }); + + function onSuccess(data) { + if (typeof(successCallback) === 'function') { + successCallback(data); + } + } + + function onFail(code) { + delete xhr[fileKey]; + if (typeof(errorCallback) === 'function') { + errorCallback(code); + } + } + }, + + download: function (successCallback, errorCallback, args) { + var source = args[0], + target = args[1], + id = args[3], + headers = args[4]; + + xhr[id] = new XMLHttpRequest({mozSystem: true}); + + xhr[id].onload = function () { + if (xhr[id].readyState === xhr[id].DONE) { + if (xhr[id].status === 200 && xhr[id].response) { + window.resolveLocalFileSystemURL(getParentPath(target), function (dir) { + dir.getFile(getFileName(target), {create: true}, writeFile, function (error) { + onFail(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR, source, target, xhr[id].status, xhr[id].response)); + }); + }, function () { + onFail(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR, source, target, xhr[id].status, xhr[id].response)); + }); + } else if (xhr[id].status === 404) { + onFail(new FileTransferError(FileTransferError.INVALID_URL_ERR, source, target, xhr[id].status, xhr[id].response)); + } else { + onFail(new FileTransferError(FileTransferError.CONNECTION_ERR, source, target, xhr[id].status, xhr[id].response)); + } + } + }; + + function writeFile(entry) { + entry.createWriter(function (fileWriter) { + fileWriter.onwriteend = function (evt) { + if (!evt.target.error) { + entry.filesystemName = entry.filesystem.name; + delete xhr[id]; + onSuccess(entry); + } else { + onFail(evt.target.error); + } + }; + fileWriter.onerror = function (evt) { + onFail(evt.target.error); + }; + fileWriter.write(new Blob([xhr[id].response])); + }, function (error) { + onFail(error); + }); + } + + xhr[id].onerror = function (e) { + onFail(new FileTransferError(FileTransferError.CONNECTION_ERR, source, target, xhr[id].status, xhr[id].response)); + }; + + xhr[id].onabort = function (e) { + onFail(new FileTransferError(FileTransferError.ABORT_ERR, source, target, xhr[id].status, xhr[id].response)); + }; + + xhr[id].open("GET", source, true); + + for (var header in headers) { + if (headers.hasOwnProperty(header)) { + xhr[id].setRequestHeader(header, headers[header]); + } + } + + xhr[id].responseType = "blob"; + + setTimeout(function () { + if (xhr[id]) { + xhr[id].send(); + } + }, 0); + + function onSuccess(entry) { + if (typeof(successCallback) === 'function') { + successCallback(entry); + } + } + + function onFail(error) { + delete xhr[id]; + if (typeof(errorCallback) === 'function') { + errorCallback(error); + } + } + } +}; + +require('cordova/exec/proxy').add('FileTransfer', module.exports);