diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d2d6946..97e4d52 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -97,3 +97,19 @@ * CB-5980 Updated version and RELEASENOTES.md for release 0.4.1 ### 0.4.5 + +### 0.4.5 (Aug 06, 2014) +* Upload parameters out of order +* **FirefoxOS** initial implementation +* CB-6781: Expose FileTransferError.exception to application +* CB-6928: Add new error code to documentation +* CB-6928: Handle 304 status code +* CB-6928: Open output stream only if it's necessary. +* [BlackBerry10] Minor doc correction +* CB-6127 Updated translations for docs +* [Windows8] upload uses the provided fileName or the actual fileName +* CB-2420 [Windows8] honor fileKey and param options. This closes #15 +* CB-6781: Update new docs to match AlexNennker's changes in PR30 +* CB-6781: Continue previous commit with one new instance (This closes #30) +* CB-6781: add the exception text to the error object +* CB-6890: Fix pluginManager access for 4.0.x branch diff --git a/doc/de/index.md b/doc/de/index.md index b767161..095c616 100644 --- a/doc/de/index.md +++ b/doc/de/index.md @@ -30,13 +30,16 @@ Dieses Plugin ermöglicht Ihnen zum Hochladen und Herunterladen von Dateien. * Amazon Fire OS * Android -* BlackBerry 10 * +* BlackBerry 10 +* Firefox OS ** * iOS * Windows Phone 7 und 8 * * Windows 8 * * *Unterstützen nicht `onprogress` noch `abort()` * +** *Unterstützen keine `onprogress` * + # FileTransfer Das `FileTransfer` Objekt bietet eine Möglichkeit zum Hochladen von Dateien, die mithilfe einer HTTP-Anforderung für mehrteiligen POST sowie Informationen zum Herunterladen von Dateien sowie. @@ -65,8 +68,6 @@ Das `FileTransfer` Objekt bietet eine Möglichkeit zum Hochladen von Dateien, di * **ErrorCallback**: ein Rückruf, der ausgeführt wird, tritt ein Fehler beim Abrufen der `Metadata` . Aufgerufene mit einem `FileTransferError` Objekt. *(Funktion)* -* **TrustAllHosts**: Optionaler Parameter, wird standardmäßig auf `false` . Wenn legen Sie auf `true` , es akzeptiert alle Sicherheitszertifikate. Dies ist nützlich, da Android selbstsignierte Zertifikate ablehnt. Nicht für den produktiven Einsatz empfohlen. Auf Android und iOS unterstützt. *(Boolean)* - * **Optionen**: optionale Parameter *(Objekt)*. Gültige Schlüssel: * **FileKey**: der Name des Form-Elements. Wird standardmäßig auf `file` . (DOM-String und enthält) @@ -76,6 +77,8 @@ Das `FileTransfer` Objekt bietet eine Möglichkeit zum Hochladen von Dateien, di * **ChunkedMode**: ob die Daten in "Chunked" streaming-Modus hochladen. Wird standardmäßig auf `true` . (Boolean) * **Header**: eine Karte von Header-Name-Header-Werte. Verwenden Sie ein Array, um mehr als einen Wert anzugeben. (Objekt) +* **TrustAllHosts**: Optionaler Parameter, wird standardmäßig auf `false` . Wenn legen Sie auf `true` , es akzeptiert alle Sicherheitszertifikate. Dies ist nützlich, da Android selbstsignierte Zertifikate ablehnt. Nicht für den produktiven Einsatz empfohlen. Auf Android und iOS unterstützt. *(Boolean)* + ### Beispiel // !! Assumes variable fileURL contains a valid URL to a text file on the device, @@ -192,7 +195,7 @@ A `FileUploadResult` -Objekt wird an den Erfolg-Rückruf des übergeben die `Fil uri, fileURL, function(entry) { - console.log("download complete: " + entry.fullPath); + console.log("download complete: " + entry.toURL()); }, function(error) { console.log("download error source " + error.source); @@ -252,12 +255,15 @@ A `FileTransferError` Objekt wird an eine Fehler-Callback übergeben, wenn ein F * **HTTP_STATUS**: HTTP-Statuscode. Dieses Attribut ist nur verfügbar, wenn ein Response-Code aus der HTTP-Verbindung eingeht. (Anzahl) +* **Ausnahme**: entweder e.getMessage oder e.toString (String) + ### Konstanten -* `FileTransferError.FILE_NOT_FOUND_ERR` -* `FileTransferError.INVALID_URL_ERR` -* `FileTransferError.CONNECTION_ERR` -* `FileTransferError.ABORT_ERR` +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` ## Hinweise rückwärts Kompatibilität diff --git a/doc/es/index.md b/doc/es/index.md index 4bb5e5d..4e27482 100644 --- a/doc/es/index.md +++ b/doc/es/index.md @@ -30,13 +30,16 @@ Este plugin te permite cargar y descargar archivos. * Amazon fuego OS * Android -* BlackBerry 10 * +* BlackBerry 10 +* Firefox OS ** * iOS * Windows Phone 7 y 8 * * Windows 8 * * *No son compatibles con `onprogress` ni `abort()` * +** *No son compatibles con `onprogress` * + # File Transfer El `FileTransfer` objeto proporciona una manera de subir archivos mediante una solicitud HTTP de POST varias parte y para descargar archivos. @@ -65,8 +68,6 @@ El `FileTransfer` objeto proporciona una manera de subir archivos mediante una s * **errorCallback**: una devolución de llamada que se ejecuta si se produce un error recuperar la `Metadata` . Invocado con un `FileTransferError` objeto. *(Función)* -* **trustAllHosts**: parámetro opcional, por defecto es `false` . Si establece en `true` , acepta todos los certificados de seguridad. Esto es útil ya que Android rechaza certificados autofirmados seguridad. No se recomienda para uso productivo. Compatible con iOS y Android. *(boolean)* - * **Opciones**: parámetros opcionales *(objeto)*. Teclas válidas: * **fileKey**: el nombre del elemento de formulario. Por defecto es `file` . (DOMString) @@ -76,6 +77,8 @@ El `FileTransfer` objeto proporciona una manera de subir archivos mediante una s * **chunkedMode**: Si desea cargar los datos en modo de transmisión fragmentado. Por defecto es `true` . (Boolean) * **cabeceras**: un mapa de valores de encabezado nombre/cabecera. Utilice una matriz para especificar más de un valor. (Objeto) +* **trustAllHosts**: parámetro opcional, por defecto es `false` . Si establece en `true` , acepta todos los certificados de seguridad. Esto es útil ya que Android rechaza certificados autofirmados seguridad. No se recomienda para uso productivo. Compatible con iOS y Android. *(boolean)* + ### Ejemplo // !! Assumes variable fileURL contains a valid URL to a text file on the device, @@ -192,7 +195,7 @@ A `FileUploadResult` objeto se pasa a la devolución del éxito de la `FileTrans uri, fileURL, function(entry) { - console.log("download complete: " + entry.fullPath); + console.log("download complete: " + entry.toURL()); }, function(error) { console.log("download error source " + error.source); @@ -252,12 +255,15 @@ A `FileTransferError` objeto se pasa a un callback de error cuando se produce un * **HTTP_STATUS**: código de estado HTTP. Este atributo sólo está disponible cuando se recibe un código de respuesta de la conexión HTTP. (Número) +* **excepción**: cualquier e.getMessage o e.toString (String) + ### Constantes -* `FileTransferError.FILE_NOT_FOUND_ERR` -* `FileTransferError.INVALID_URL_ERR` -* `FileTransferError.CONNECTION_ERR` -* `FileTransferError.ABORT_ERR` +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` ## Al revés notas de compatibilidad diff --git a/doc/fr/index.md b/doc/fr/index.md index defdba7..39978c9 100644 --- a/doc/fr/index.md +++ b/doc/fr/index.md @@ -30,16 +30,19 @@ Ce plugin vous permet de télécharger des fichiers. * Amazon Fire OS * Android -* BlackBerry 10 * +* BlackBerry 10 +* Firefox OS ** * iOS * Windows Phone 7 et 8 * * Windows 8 * * *Ne supportent pas `onprogress` ni `abort()` * +** *Ne prennent pas en charge `onprogress` * + # Transfert de fichiers -L'objet `FileTransfer` fournit un moyen de tranférer des fichiers sur un serveur HTTP avec une requête multi-part POST, et aussi pour télécharger des fichiers. +Le `FileTransfer` objet fournit un moyen de télécharger des fichiers à l'aide d'une requête HTTP de la poste plusieurs partie et pour télécharger des fichiers aussi bien. ## Propriétés @@ -65,16 +68,16 @@ L'objet `FileTransfer` fournit un moyen de tranférer des fichiers sur un serveu * **errorCallback** : callback d'erreur s'exécutant si une erreur survient lors de la récupération de l'objet `Metadata` . Appelée avec un objet `FileTransferError`. *(Function)* -* **trustAllHosts** : paramètre facultatif, sa valeur par défaut est `false`. Si sa valeur est réglée à `true`, tous les certificats de sécurité sont acceptés. Ceci peut être utile car Android rejette les certificats auto-signés. N'est pas recommandé pour une utilisation en production. Supporté sous Android et iOS. *(boolean)* - * **options**: paramètres facultatifs *(objet)*. Clés valides : - * **fileKey** : le nom de l'élément form. La valeur par défaut est `file`. (DOMString) - * **fileName** : le nom de fichier à utiliser pour l'enregistrement sur le serveur. La valeur par défaut est `image.jpg`. (DOMString) - * **mimeType** : le type mime des données à envoyer. La valeur par défaut est `image/jpeg`. (DOMString) - * **params** : un ensemble de paires clé/valeur facultative à passer dans la requête HTTP. (Objet) - * **chunkedMode** : s'il faut transmettre ou non les données en mode streaming de bloc. La valeur par défaut est `true`. (Boolean) - * **headers** : un objet représentant les noms et valeurs d'en-têtes à transmettre. Utiliser un tableau permet de spécifier plusieurs valeurs. (Objet) + * **fileKey**: le nom de l'élément form. Valeur par défaut est `file` . (DOMString) + * **fileName**: le nom de fichier à utiliser lorsque vous enregistrez le fichier sur le serveur. Valeur par défaut est `image.jpg` . (DOMString) + * **type MIME**: le type mime des données à télécharger. Valeur par défaut est `image/jpeg` . (DOMString) + * **params**: un ensemble de paires clé/valeur facultative pour passer dans la requête HTTP. (Objet) + * **chunkedMode**: s'il faut télécharger les données en mode streaming mémorisé en bloc. Valeur par défaut est `true` . (Boolean) + * **en-têtes**: une carte des valeurs d'en-tête en-tête/nom. Un tableau permet de spécifier plusieurs valeurs. (Objet) + +* **trustAllHosts**: paramètre facultatif, valeur par défaut est `false` . Si la valeur `true` , il accepte tous les certificats de sécurité. Ceci est utile car Android rejette des certificats auto-signés. Non recommandé pour une utilisation de production. Supporté sur Android et iOS. *(boolean)* ### Exemple @@ -146,7 +149,7 @@ L'objet `FileTransfer` fournit un moyen de tranférer des fichiers sur un serveu ## FileUploadResult -Un objet `FileUploadResult` est passé à la callback de succès de la méthode `upload()` de l'objet `FileTransfer`. +A `FileUploadResult` objet est passé au rappel de succès la `FileTransfer` de l'objet `upload()` méthode. ### Propriétés @@ -192,7 +195,7 @@ Un objet `FileUploadResult` est passé à la callback de succès de la méthode uri, fileURL, function(entry) { - console.log("download complete: " + entry.fullPath); + console.log("download complete: " + entry.toURL()); }, function(error) { console.log("download error source " + error.source); @@ -210,7 +213,7 @@ Un objet `FileUploadResult` est passé à la callback de succès de la méthode ## abort -Abandonne un transfert en cours. Un objet FileTransferError avec un code d'erreur FileTransferError.ABORT_ERR est passé à la callback d'erreur onerror. +Abandonne un transfert en cours. Le rappel onerror est passé à un objet FileTransferError qui a un code d'erreur de FileTransferError.ABORT_ERR. ### Exemple @@ -240,7 +243,7 @@ Abandonne un transfert en cours. Un objet FileTransferError avec un code d'erreu ## FileTransferError -Un objet `FileTransferError` est passé à une callback d'erreur lorsqu'une erreur survient. +A `FileTransferError` objet est passé à un rappel d'erreur lorsqu'une erreur survient. ### Propriétés @@ -252,30 +255,33 @@ Un objet `FileTransferError` est passé à une callback d'erreur lorsqu'une erre * **http_status** : code d'état HTTP. Cet attribut n'est disponible que lorsqu'un code de réponse est fourni via la connexion HTTP. (Number) +* **exception**: soit e.getMessage ou e.toString (String) + ### Constantes -* `FileTransferError.FILE_NOT_FOUND_ERR` -* `FileTransferError.INVALID_URL_ERR` -* `FileTransferError.CONNECTION_ERR` -* `FileTransferError.ABORT_ERR` +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` ## Backwards Compatibility Notes -Les versions précédentes de ce plugin accepte seulement les chemins de fichiers périphérique absolus comme source pour les chargement, ou comme cible pour les téléchargements. Ces chemins sont généralement de la forme +Les versions précédentes de ce plugin n'accepterait périphérique--fichier-chemins d'accès absolus comme source pour les téléchargements, ou comme cible pour les téléchargements. Ces chemins seraient généralement de la forme /var/mobile/Applications//Documents/path/to/file (iOS) /storage/emulated/0/path/to/file (Android) -Pour la compatibilité ascendante, ces chemins sont toujours acceptés, et si votre application a enregistré des chemins comme ceux-ci dans un stockage persistant, alors ils peuvent continuer à être utilisé. +Pour vers l'arrière la compatibilité, ces chemins sont toujours acceptés, et si votre application a enregistré des chemins comme celles-ci dans un stockage persistant, alors ils peuvent continuer à être utilisé. -Ces chemins ont été précédemment exposés dans la propriété `fullPath` de `FileEntry` et objets `DirectoryEntry` retournés par le fichier plugin. Nouvelles versions du fichier plugin, cependant, ne plus exposer ces chemins à JavaScript. +Ces chemins ont été précédemment exposés dans le `fullPath` propriété de `FileEntry` et `DirectoryEntry` les objets retournés par le fichier plugin. Nouvelles versions du fichier plugin, cependant, ne plus exposent ces chemins à JavaScript. -Si vous migrez vers une nouvelle version du fichier (1.0.0 ou plus récent) et que vous utilisiez précédemment `entry.fullPath` en tant qu'arguments à `download()` ou `upload()`, alors vous aurez besoin de modifier votre code pour utiliser le système de fichiers URL à la place. +Si vous migrez vers une nouvelle (1.0.0 ou plus récent) version de fichier et vous avez précédemment utilisé `entry.fullPath` comme arguments à `download()` ou `upload()` , alors vous aurez besoin de modifier votre code pour utiliser le système de fichiers URL au lieu de cela. -`FileEntry.toURL()` et `DirectoryEntry.toURL()` retournent une URL de système de fichier de formulaire +`FileEntry.toURL()`et `DirectoryEntry.toURL()` retournent une URL de système de fichiers du formulaire cdvfile://localhost/persistent/path/to/file -qui peut être utilisé à la place du chemin d'accès absolu au fichier dans les méthodes `download()` et `upload()`. \ No newline at end of file +qui peut être utilisé à la place le chemin d'accès absolu au fichier dans les deux `download()` et `upload()` méthodes. \ No newline at end of file diff --git a/doc/index.md b/doc/index.md index f8bcbeb..48b14b2 100644 --- a/doc/index.md +++ b/doc/index.md @@ -29,13 +29,19 @@ This plugin allows you to upload and download files. - Amazon Fire OS - Android -- BlackBerry 10* +- BlackBerry 10 +- Firefox OS** - iOS - Windows Phone 7 and 8* -- Windows 8* +- Windows 8*** +- Windows*** \* _Do not support `onprogress` nor `abort()`_ +\** _Do not support `onprogress`_ + +\*** Partial support of `onprogress` for upload method. `onprogress` is called with empty progress event due to Windows limitations_ + # FileTransfer The `FileTransfer` object provides a way to upload files using an HTTP @@ -66,8 +72,6 @@ __Parameters__: - __errorCallback__: A callback that executes if an error occurs retrieving the `Metadata`. Invoked with a `FileTransferError` object. _(Function)_ -- __trustAllHosts__: Optional parameter, defaults to `false`. If set to `true`, it accepts all security certificates. This is useful since Android rejects self-signed security certificates. Not recommended for production use. Supported on Android and iOS. _(boolean)_ - - __options__: Optional parameters _(Object)_. Valid keys: - __fileKey__: The name of the form element. Defaults to `file`. (DOMString) - __fileName__: The file name to use when saving the file on the server. Defaults to `image.jpg`. (DOMString) @@ -75,6 +79,8 @@ __Parameters__: - __params__: A set of optional key/value pairs to pass in the HTTP request. (Object) - __chunkedMode__: Whether to upload the data in chunked streaming mode. Defaults to `true`. (Boolean) - __headers__: A map of header name/header values. Use an array to specify more than one value. (Object) + +- __trustAllHosts__: Optional parameter, defaults to `false`. If set to `true`, it accepts all security certificates. This is useful since Android rejects self-signed security certificates. Not recommended for production use. Supported on Android and iOS. _(boolean)_ ### Example @@ -257,6 +263,7 @@ A `FileTransferError` object is passed to an error callback when an error occurs - 2 = `FileTransferError.INVALID_URL_ERR` - 3 = `FileTransferError.CONNECTION_ERR` - 4 = `FileTransferError.ABORT_ERR` +- 5 = `FileTransferError.NOT_MODIFIED_ERR` ## Backwards Compatibility Notes diff --git a/doc/it/index.md b/doc/it/index.md index 89c32b4..be17a9b 100644 --- a/doc/it/index.md +++ b/doc/it/index.md @@ -30,13 +30,16 @@ Questo plugin permette di caricare e scaricare file. * Amazon fuoco OS * Android -* BlackBerry 10 * +* BlackBerry 10 +* Firefox OS * * * iOS * Windows Phone 7 e 8 * * Windows 8 * * *Non supportano `onprogress` né `abort()` * +* * *Non supportano `onprogress` * + # FileTransfer Il `FileTransfer` oggetto fornisce un modo per caricare i file utilizzando una richiesta HTTP di POST più parte e scaricare file pure. @@ -65,8 +68,6 @@ Il `FileTransfer` oggetto fornisce un modo per caricare i file utilizzando una r * **errorCallback**: un callback che viene eseguito se si verifica un errore recuperando il `Metadata` . Invocato con un `FileTransferError` oggetto. *(Funzione)* -* **trustAllHosts**: parametro opzionale, valore predefinito è `false` . Se impostata su `true` , accetta tutti i certificati di sicurezza. Questo è utile poiché Android respinge i certificati autofirmati sicurezza. Non raccomandato per uso in produzione. Supportato su Android e iOS. *(boolean)* - * **opzioni**: parametri facoltativi *(oggetto)*. Chiavi valide: * **fileKey**: il nome dell'elemento form. Valore predefinito è `file` . (DOMString) @@ -76,6 +77,8 @@ Il `FileTransfer` oggetto fornisce un modo per caricare i file utilizzando una r * **chunkedMode**: se a caricare i dati in modalità streaming chunked. Valore predefinito è `true` . (Boolean) * **intestazioni**: mappa di valori nome/intestazione intestazione. Utilizzare una matrice per specificare più valori. (Oggetto) +* **trustAllHosts**: parametro opzionale, valore predefinito è `false` . Se impostata su `true` , accetta tutti i certificati di sicurezza. Questo è utile poiché Android respinge i certificati autofirmati sicurezza. Non raccomandato per uso in produzione. Supportato su Android e iOS. *(boolean)* + ### Esempio // !! Assumes variable fileURL contains a valid URL to a text file on the device, @@ -192,7 +195,7 @@ A `FileUploadResult` oggetto viene passato al metodo di callback di successo il uri, fileURL, function(entry) { - console.log("download complete: " + entry.fullPath); + console.log("download complete: " + entry.toURL()); }, function(error) { console.log("download error source " + error.source); @@ -252,12 +255,15 @@ A `FileTransferError` oggetto viene passato a un callback di errore quando si ve * **http_status**: codice di stato HTTP. Questo attributo è disponibile solo quando viene ricevuto un codice di risposta della connessione HTTP. (Numero) +* **eccezione**: O e.getMessage o e.toString (String) + ### Costanti -* `FileTransferError.FILE_NOT_FOUND_ERR` -* `FileTransferError.INVALID_URL_ERR` -* `FileTransferError.CONNECTION_ERR` -* `FileTransferError.ABORT_ERR` +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` ## Note di compatibilità all'indietro diff --git a/doc/ja/index.md b/doc/ja/index.md index ef7883a..d8aefcb 100644 --- a/doc/ja/index.md +++ b/doc/ja/index.md @@ -30,13 +30,16 @@ * アマゾン火 OS * アンドロイド -* ブラックベリー 10 * +* ブラックベリー 10 +* Firefox の OS * * * iOS * Windows Phone 7 と 8 * * Windows 8 * **サポートしていない `onprogress` も `abort()` * +* **サポートしていない `onprogress` * + # ファイル転送 `FileTransfer`オブジェクトはマルチパートのポスト、HTTP 要求を使用してファイルをアップロードして同様にファイルをダウンロードする方法を提供します。 @@ -65,8 +68,6 @@ * **解り**: エラー取得が発生した場合に実行されるコールバック、 `Metadata` 。呼び出されると、 `FileTransferError` オブジェクト。*(機能)* -* **trustAllHosts**: 省略可能なパラメーターは、デフォルト `false` 。 場合設定 `true` 、セキュリティ証明書をすべて受け付けます。 これは Android の自己署名入りセキュリティ証明書を拒否するので便利です。 運用環境で使用しないでください。 Android と iOS でサポートされています。 *(ブール値)* - * **オプション**: 省略可能なパラメーター *(オブジェクト)*。有効なキー: * **fileKey**: フォーム要素の名前。既定値は `file` です。(,) @@ -76,6 +77,8 @@ * **chunkedMode**: チャンク ストリーミング モードでデータをアップロードするかどうか。既定値は `true` です。(ブール値) * **ヘッダー**: ヘッダーの名前/ヘッダー値のマップ。1 つ以上の値を指定するには、配列を使用します。(オブジェクト) +* **trustAllHosts**: 省略可能なパラメーターは、デフォルト `false` 。 場合設定 `true` 、セキュリティ証明書をすべて受け付けます。 これは Android の自己署名入りセキュリティ証明書を拒否するので便利です。 運用環境で使用しないでください。 Android と iOS でサポートされています。 *(ブール値)* + ### 例 // !! Assumes variable fileURL contains a valid URL to a text file on the device, @@ -192,7 +195,7 @@ A `FileUploadResult` オブジェクトの成功時のコールバックに渡 uri, fileURL, function(entry) { - console.log("download complete: " + entry.fullPath); + console.log("download complete: " + entry.toURL()); }, function(error) { console.log("download error source " + error.source); @@ -252,12 +255,15 @@ A `FileTransferError` オブジェクトは、エラーが発生エラー コー * **http_status**: HTTP ステータス コード。この属性は、HTTP 接続から応答コードを受信したときにのみ使用できます。(数) +* **例外**: どちらか e.getMessage または e.toString (文字列) + ### 定数 -* `FileTransferError.FILE_NOT_FOUND_ERR` -* `FileTransferError.INVALID_URL_ERR` -* `FileTransferError.CONNECTION_ERR` -* `FileTransferError.ABORT_ERR` +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` ## 後方互換性をノートします。 diff --git a/doc/ko/index.md b/doc/ko/index.md index 109cf80..5c76fd2 100644 --- a/doc/ko/index.md +++ b/doc/ko/index.md @@ -30,13 +30,16 @@ * 아마존 화재 운영 체제 * 안 드 로이드 -* 블랙베리 10 * +* 블랙베리 10 +* 파이어 폭스 OS * * * iOS * Windows Phone 7과 8 * * 윈도우 8 * * *를 지원 하지 않는 `onprogress` 도 `abort()` * +* * *를 지원 하지 않는 `onprogress` * + # FileTransfer `FileTransfer`개체는 HTTP 다중 파트 POST 요청을 사용 하 여 파일을 업로드 하 고 뿐만 아니라 파일을 다운로드 하는 방법을 제공 합니다. @@ -65,8 +68,6 @@ * **errorCallback**: 콜백 검색에 오류가 발생 하면 실행 되는 `Metadata` . 로 호출을 `FileTransferError` 개체. *(기능)* -* **trustAllHosts**: 선택적 매개 변수는 기본적으로 `false` . 만약 설정 `true` , 그것은 모든 보안 인증서를 허용 합니다. 이 안 드 로이드 자체 서명 된 보안 인증서를 거부 하기 때문에 유용 합니다. 프로덕션 환경에서 사용 권장 되지 않습니다. 안 드 로이드와 iOS에서 지원. *(부울)* - * **옵션**: 선택적 매개 변수 *(개체)*. 유효한 키: * **fileKey**: form 요소의 이름. 기본값은 `file` . (DOMString) @@ -76,6 +77,8 @@ * **chunkedMode**: 청크 스트리밍 모드에서 데이터 업로드를 합니다. 기본값은 `true` . (부울) * **헤더**: 헤더 이름/헤더 값의 지도. 배열을 사용 하 여 하나 이상의 값을 지정 합니다. (개체) +* **trustAllHosts**: 선택적 매개 변수는 기본적으로 `false` . 만약 설정 `true` , 그것은 모든 보안 인증서를 허용 합니다. 이 안 드 로이드 자체 서명 된 보안 인증서를 거부 하기 때문에 유용 합니다. 프로덕션 환경에서 사용 권장 되지 않습니다. 안 드 로이드와 iOS에서 지원. *(부울)* + ### 예를 들어 // !! Assumes variable fileURL contains a valid URL to a text file on the device, @@ -192,7 +195,7 @@ A `FileUploadResult` 개체의 성공 콜백에 전달 되는 `FileTransfer` 개 uri, fileURL, function(entry) { - console.log("download complete: " + entry.fullPath); + console.log("download complete: " + entry.toURL()); }, function(error) { console.log("download error source " + error.source); @@ -252,12 +255,15 @@ A `FileTransferError` 오류가 발생 하면 오류 콜백 개체 전달 됩니 * **http_status**: HTTP 상태 코드. 이 특성은 응답 코드를 HTTP 연결에서 수신에 사용할 수 있습니다. (수) +* **예외**: 어느 e.getMessage 또는 e.toString (문자열) + ### 상수 -* `FileTransferError.FILE_NOT_FOUND_ERR` -* `FileTransferError.INVALID_URL_ERR` -* `FileTransferError.CONNECTION_ERR` -* `FileTransferError.ABORT_ERR` +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` ## 이전 버전과 호환성 노트 diff --git a/doc/pl/index.md b/doc/pl/index.md index 32829af..e3b38cd 100644 --- a/doc/pl/index.md +++ b/doc/pl/index.md @@ -30,13 +30,16 @@ Plugin pozwala na przesyłanie i pobieranie plików. * Amazon ogień OS * Android -* Jeżyna 10 * +* Jeżyna 10 +* Firefox OS ** * iOS * Windows Phone 7 i 8 * * Windows 8 * * *Nie obsługują `onprogress` ani `abort()` * +** *Nie obsługują `onprogress` * + # FileTransfer `FileTransfer`Obiekt zapewnia sposób wgrać pliki przy użyciu żądania HTTP wieloczęściowe POST i pobierania plików, jak również. @@ -65,8 +68,6 @@ Plugin pozwala na przesyłanie i pobieranie plików. * **errorCallback**: wywołanie zwrotne, które wykonuje, jeżeli wystąpi błąd pobierania `Metadata` . Wywołany z `FileTransferError` obiektu. *(Funkcja)* -* **trustAllHosts**: parametr opcjonalny, domyślnie `false` . Jeśli zestaw `true` , to akceptuje wszystkie certyfikaty bezpieczeństwa. Jest to przydatne, ponieważ Android odrzuca Certyfikaty samopodpisane. Nie zaleca się do użytku produkcyjnego. Obsługiwane na Androida i iOS. *(wartość logiczna)* - * **Opcje**: parametry opcjonalne *(obiektu)*. Ważne klucze: * **fileKey**: nazwa elementu form. Domyślnie `file` . (DOMString) @@ -76,6 +77,8 @@ Plugin pozwala na przesyłanie i pobieranie plików. * **chunkedMode**: czy przekazać dane w trybie pakietowego przesyłania strumieniowego. Domyślnie `true` . (Wartość logiczna) * **nagłówki**: Mapa wartości Nazwa/nagłówka nagłówek. Aby określić więcej niż jedną wartość, należy użyć tablicę. (Obiekt) +* **trustAllHosts**: parametr opcjonalny, domyślnie `false` . Jeśli zestaw `true` , to akceptuje wszystkie certyfikaty bezpieczeństwa. Jest to przydatne, ponieważ Android odrzuca Certyfikaty samopodpisane. Nie zaleca się do użytku produkcyjnego. Obsługiwane na Androida i iOS. *(wartość logiczna)* + ### Przykład // !! Assumes variable fileURL contains a valid URL to a text file on the device, @@ -192,7 +195,7 @@ A `FileUploadResult` obiekt jest przekazywany do funkcji callback sukces z `File uri, fileURL, function(entry) { - console.log("download complete: " + entry.fullPath); + console.log("download complete: " + entry.toURL()); }, function(error) { console.log("download error source " + error.source); @@ -252,12 +255,15 @@ A `FileTransferError` obiekt jest przekazywany do wywołania zwrotnego błąd, g * **HTTP_STATUS**: kod stanu HTTP. Ten atrybut jest dostępna tylko po otrzymaniu kodu odpowiedzi z połączenia HTTP. (Liczba) +* **wyjątek**: albo e.getMessage lub e.toString (String) + ### Stałe -* `FileTransferError.FILE_NOT_FOUND_ERR` -* `FileTransferError.INVALID_URL_ERR` -* `FileTransferError.CONNECTION_ERR` -* `FileTransferError.ABORT_ERR` +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` ## Do tyłu zgodności stwierdza diff --git a/doc/ru/index.md b/doc/ru/index.md new file mode 100644 index 0000000..5cb6d40 --- /dev/null +++ b/doc/ru/index.md @@ -0,0 +1,287 @@ + + +# org.apache.cordova.file-transfer + +Этот плагин позволяет вам загружать и скачивать файлы. + +## Установка + + cordova plugin add org.apache.cordova.file-transfer + + +## Поддерживаемые платформы + +* Amazon Fire ОС +* Android +* BlackBerry 10 +* Firefox OS ** +* iOS +* Windows Phone 7 и 8 * +* Windows 8 * + +* *Не поддерживают `onprogress` , ни `abort()` * + +** *Не поддерживает `onprogress` * + +# FileTransfer + +`FileTransfer`Объект предоставляет способ для загрузки файлов с помощью нескольких частей запроса POST HTTP и для загрузки файлов, а также. + +## Свойства + +* **OnProgress**: называется с `ProgressEvent` всякий раз, когда новый фрагмент данных передается. *(Функция)* + +## Методы + +* **добавлено**: отправляет файл на сервер. + +* **скачать**: Скачать файл с сервера. + +* **прервать**: прерывает передачу в прогресс. + +## загрузить + +**Параметры**: + +* **fileURL**: файловой системы URL-адрес, представляющий файл на устройстве. Для обратной совместимости, это также может быть полный путь к файлу на устройстве. (См. [обратной совместимости отмечает] ниже) + +* **сервер**: URL-адрес сервера, чтобы получить файл, как закодированные`encodeURI()`. + +* **successCallback**: обратного вызова, передаваемого `Metadata` объект. *(Функция)* + +* **errorCallback**: обратного вызова, который выполняется в случае получения ошибки `Metadata` . Вызываемый с `FileTransferError` объект. *(Функция)* + +* **опции**: необязательные параметры *(объект)*. Допустимые ключи: + + * **fileKey**: имя элемента form. По умолчанию `file` . (DOMString) + * **имя файла**: имя файла для использования при сохранении файла на сервере. По умолчанию `image.jpg` . (DOMString) + * **mimeType**: mime-тип данных для загрузки. По умолчанию `image/jpeg` . (DOMString) + * **params**: набор пар дополнительный ключ/значение для передачи в HTTP-запросе. (Объект) + * **chunkedMode**: следует ли загружать данные в фрагментарности потоковом режиме. По умолчанию `true` . (Логическое значение) + * **заголовки**: Карта значений заголовок имя заголовка. Используйте массив для указания более одного значения. (Объект) + +* **trustAllHosts**: необязательный параметр, по умолчанию `false` . Если значение `true` , она принимает все сертификаты безопасности. Это полезно, поскольку Android отвергает самозаверяющие сертификаты. Не рекомендуется для использования в производстве. Поддерживается на Android и iOS. *(логическое значение)* + +### Пример + + // !! Assumes variable fileURL contains a valid URL to a text file on the device, + // for example, cdvfile://localhost/persistent/path/to/file.txt + + var win = function (r) { + console.log("Code = " + r.responseCode); + console.log("Response = " + r.response); + console.log("Sent = " + r.bytesSent); + } + + var fail = function (error) { + alert("An error has occurred: Code = " + error.code); + console.log("upload error source " + error.source); + console.log("upload error target " + error.target); + } + + var options = new FileUploadOptions(); + options.fileKey = "file"; + options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1); + options.mimeType = "text/plain"; + + var params = {}; + params.value1 = "test"; + params.value2 = "param"; + + options.params = params; + + var ft = new FileTransfer(); + ft.upload(fileURL, encodeURI("http://some.server.com/upload.php"), win, fail, options); + + +### Пример с загружать заголовки и события Progress (Android и iOS только) + + function win(r) { + console.log("Code = " + r.responseCode); + console.log("Response = " + r.response); + console.log("Sent = " + r.bytesSent); + } + + function fail(error) { + alert("An error has occurred: Code = " + error.code); + console.log("upload error source " + error.source); + console.log("upload error target " + error.target); + } + + var uri = encodeURI("http://some.server.com/upload.php"); + + var options = new FileUploadOptions(); + options.fileKey="file"; + options.fileName=fileURL.substr(fileURL.lastIndexOf('/')+1); + options.mimeType="text/plain"; + + var headers={'headerParam':'headerValue'}; + + options.headers = headers; + + var ft = new FileTransfer(); + ft.onprogress = function(progressEvent) { + if (progressEvent.lengthComputable) { + loadingStatus.setPercentage(progressEvent.loaded / progressEvent.total); + } else { + loadingStatus.increment(); + } + }; + ft.upload(fileURL, uri, win, fail, options); + + +## FileUploadResult + +A `FileUploadResult` объект передается методу обратного вызова успех `FileTransfer` объекта `upload()` метод. + +### Свойства + +* **bytesSent**: количество байт, отправленных на сервер как часть загрузки. (длинная) + +* **responseCode**: код ответа HTTP, возвращаемых сервером. (длинная) + +* **ответ**: ответ HTTP, возвращаемых сервером. (DOMString) + +* **заголовки**: заголовки ответов HTTP-сервером. (Объект) + + * В настоящее время поддерживается только для iOS. + +### iOS причуды + +* Не поддерживает `responseCode` или`bytesSent`. + +## Скачать + +**Параметры**: + +* **источник**: URL-адрес сервера для загрузки файла, как закодированные`encodeURI()`. + +* **Цель**: файловой системы URL-адрес, представляющий файл на устройстве. Для обратной совместимости, это также может быть полный путь к файлу на устройстве. (См. [обратной совместимости отмечает] ниже) + +* **successCallback**: обратного вызова, передаваемого `FileEntry` объект. *(Функция)* + +* **errorCallback**: обратного вызова, который выполняется, если возникает ошибка при получении `Metadata` . Вызываемый с `FileTransferError` объект. *(Функция)* + +* **trustAllHosts**: необязательный параметр, по умолчанию `false` . Если значение `true` , она принимает все сертификаты безопасности. Это полезно, потому что Android отвергает самозаверяющие сертификаты. Не рекомендуется для использования в производстве. Поддерживается на Android и iOS. *(логическое значение)* + +* **опции**: необязательные параметры, в настоящее время только поддерживает заголовки (например авторизации (базовая аутентификация) и т.д.). + +### Пример + + // !! Assumes variable fileURL contains a valid URL to a path on the device, + // for example, cdvfile://localhost/persistent/path/to/downloads/ + + var fileTransfer = new FileTransfer(); + var uri = encodeURI("http://some.server.com/download.php"); + + fileTransfer.download( + uri, + fileURL, + function(entry) { + console.log("download complete: " + entry.toURL()); + }, + function(error) { + console.log("download error source " + error.source); + console.log("download error target " + error.target); + console.log("upload error code" + error.code); + }, + false, + { + headers: { + "Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA==" + } + } + ); + + +## прервать + +Прерывает передачу в прогресс. Onerror обратного вызова передается объект FileTransferError, который имеет код ошибки FileTransferError.ABORT_ERR. + +### Пример + + // !! Assumes variable fileURL contains a valid URL to a text file on the device, + // for example, cdvfile://localhost/persistent/path/to/file.txt + + var win = function(r) { + console.log("Should not be called."); + } + + var fail = function(error) { + // error.code == FileTransferError.ABORT_ERR + alert("An error has occurred: Code = " + error.code); + console.log("upload error source " + error.source); + console.log("upload error target " + error.target); + } + + var options = new FileUploadOptions(); + options.fileKey="file"; + options.fileName="myphoto.jpg"; + options.mimeType="image/jpeg"; + + var ft = new FileTransfer(); + ft.upload(fileURL, encodeURI("http://some.server.com/upload.php"), win, fail, options); + ft.abort(); + + +## FileTransferError + +A `FileTransferError` при ошибке обратного вызова передается объект, при возникновении ошибки. + +### Свойства + +* **код**: один из кодов стандартных ошибок, перечисленные ниже. (Число) + +* **источник**: URL-адрес источника. (Строка) + +* **Цель**: URL-адрес к целевому объекту. (Строка) + +* **http_status**: код состояния HTTP. Этот атрибут доступен только при код ответа от HTTP-соединения. (Число) + +* **исключение**: либо e.getMessage или e.toString (строка) + +### Константы + +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` + +## Обратной совместимости отмечает + +Предыдущие версии этого плагина будет принимать только устройства Абсолют файлам как источник для закачки, или как целевых для загрузок. Обычно эти пути бы формы + + /var/mobile/Applications//Documents/path/to/file (iOS) + /storage/emulated/0/path/to/file (Android) + + +Для обратной совместимости, по-прежнему принимаются эти пути, и если ваше приложение зарегистрировано пути как в постоянное хранилище, то они могут продолжать использоваться. + +Эти пути ранее были видны в `fullPath` свойства `FileEntry` и `DirectoryEntry` объекты, возвращаемые файл плагина. Новые версии файла плагина, однако, не подвергать эти пути в JavaScript. + +Если вы переходите на новый (1.0.0 или новее) версию файла и вы ранее использовали `entry.fullPath` в качестве аргументов `download()` или `upload()` , то вам необходимо будет изменить код для использования файловой системы URL вместо. + +`FileEntry.toURL()`и `DirectoryEntry.toURL()` возвращает URL-адрес формы файловой системы + + cdvfile://localhost/persistent/path/to/file + + +которые могут быть использованы вместо абсолютного пути в обоих `download()` и `upload()` методы. \ No newline at end of file diff --git a/doc/zh/index.md b/doc/zh/index.md index 36a3b15..fb05a5e 100644 --- a/doc/zh/index.md +++ b/doc/zh/index.md @@ -30,16 +30,19 @@ * 亞馬遜火 OS * Android 系統 -* 黑莓 10 * +* 黑莓 10 +* 火狐瀏覽器作業系統 * * * iOS * Windows Phone 7 和 8 * * Windows 8 * **不支援 `onprogress` ,也不 `abort()` * +* **不支援 `onprogress` * + # 檔案傳輸 -`FileTransfer`物件提供一種方法來使用 HTTP 多部分 POST 請求的檔上傳和下載檔案,以及。 +`FileTransfer`物件提供一種方法使用 HTTP 多部分 POST 請求的檔上傳和下載檔案,以及。 ## 屬性 @@ -65,16 +68,16 @@ * **errorCallback**: 回檔的執行如果出現檢索錯誤 `Metadata` 。調用與 `FileTransferError` 物件。*(函數)* -* **trustAllHosts**: 可選參數,預設值為 `false` 。 如果設置為 `true` ,它可以接受的所有安全證書。 由於 Android 拒絕自行簽署式安全證書,這非常有用。 不建議供生產使用。 在 Android 和 iOS 上受支援。 *(布林值)* - * **選項**: 可選參數*(物件)*。有效的金鑰: * **fileKey**: 表單元素的名稱。預設值為 `file` 。() DOMString * **檔案名**: 要保存在伺服器上的檔時使用的檔案名稱。預設值為 `image.jpg` 。() DOMString * **mimeType**: 要上傳的資料的 mime 類型。預設值為 `image/jpeg` 。() DOMString - * **params**: 一組可選的鍵/值對中的 HTTP 要求的傳遞。(物件) + * **params**: 一組可選的鍵/值對在 HTTP 要求中傳遞。(物件) * **chunkedMode**: 是否要分塊流式處理模式中的資料上載。預設值為 `true` 。(布林值) - * **標題**: 一張地圖的標頭名稱/標頭值。使用陣列來指定多個值。(物件) + * **標題**: 地圖的標頭名稱/標頭值。使用陣列來指定多個值。(物件) + +* **trustAllHosts**: 可選參數,預設值為 `false` 。 如果設置為 `true` ,它接受的所有安全證書。 這是有用的因為 android 系統拒絕自簽名的安全證書。 不建議供生產使用。 支援 Android 和 iOS。 *(布林值)* ### 示例 @@ -192,7 +195,7 @@ A `FileUploadResult` 物件傳遞給成功回檔的 `FileTransfer` 物件的 `up uri, fileURL, function(entry) { - console.log("download complete: " + entry.fullPath); + console.log("download complete: " + entry.toURL()); }, function(error) { console.log("download error source " + error.source); @@ -240,7 +243,7 @@ A `FileUploadResult` 物件傳遞給成功回檔的 `FileTransfer` 物件的 `up ## FileTransferError -A `FileTransferError` 物件傳遞到錯誤回檔時出現錯誤。 +A `FileTransferError` 物件被傳遞給一個錯誤回呼函數時出現錯誤。 ### 屬性 @@ -252,30 +255,33 @@ A `FileTransferError` 物件傳遞到錯誤回檔時出現錯誤。 * **HTTP_status**: HTTP 狀態碼。從 HTTP 連接收到一個回應代碼時,此屬性才可用。(人數) +* **例外**: 要麼 e.getMessage 或 e.toString (字串) + ### 常量 -* `FileTransferError.FILE_NOT_FOUND_ERR` -* `FileTransferError.INVALID_URL_ERR` -* `FileTransferError.CONNECTION_ERR` -* `FileTransferError.ABORT_ERR` +* 1 = `FileTransferError.FILE_NOT_FOUND_ERR` +* 2 = `FileTransferError.INVALID_URL_ERR` +* 3 = `FileTransferError.CONNECTION_ERR` +* 4 = `FileTransferError.ABORT_ERR` +* 5 = `FileTransferError.NOT_MODIFIED_ERR` ## 向後相容性注意到 -以前版本的這個外掛程式將只接受設備絕對檔路徑作為源的上載,或為下載的目標。這些路徑通常將表單的 +以前版本的這個外掛程式才會接受設備-絕對檔路徑的源上傳,或作為下載的目標。這些路徑通常會在表單 /var/mobile/Applications//Documents/path/to/file (iOS) /storage/emulated/0/path/to/file (Android) -為向後相容性,這些路徑仍被接受,和如果您的應用程式已錄得像這些持久性存儲區中的路徑,然後他們可以繼續使用。 +為向後相容性,這些路徑仍被接受,和如果您的應用程式記錄了像這些在持久性存儲的路徑,然後他們可以繼續使用。 -這些路徑以前被暴露在 `fullPath` 屬性的 `FileEntry` 和 `DirectoryEntry` 由檔外掛程式返回的物件。 新版本的檔的外掛程式,不過,不再公開這些 JavaScript 的路徑。 +這些路徑被以前暴露在 `fullPath` 屬性的 `FileEntry` 和 `DirectoryEntry` 由檔外掛程式返回的物件。 新版本的檔的外掛程式,不過,不再公開這些 JavaScript 的路徑。 -如果您要升級到一個新的 (1.0.0 或更高版本) 版本的檔,和你以前一直在使用 `entry.fullPath` 作為的參數 `download()` 或 `upload()` ,那麼您將需要更改您的代碼,而使用的檔案系統的 Url。 +如果您升級到一個新 (1.0.0 或更高版本) 版本的檔,和你以前一直在使用 `entry.fullPath` 作為的參數 `download()` 或 `upload()` ,那麼你將需要更改代碼以使用檔案系統的 Url 來代替。 `FileEntry.toURL()`和 `DirectoryEntry.toURL()` 返回的表單檔案系統 URL cdvfile://localhost/persistent/path/to/file -可以使用在中兩者的絕對檔路徑位置 `download()` 和 `upload()` 方法。 \ No newline at end of file +其中可代替的絕對檔路徑在兩個 `download()` 和 `upload()` 的方法。 \ No newline at end of file diff --git a/plugin.xml b/plugin.xml index a0e585e..9e29e95 100644 --- a/plugin.xml +++ b/plugin.xml @@ -21,7 +21,7 @@ + version="0.4.6-dev"> File Transfer Cordova File Transfer Plugin Apache 2.0 @@ -139,9 +139,26 @@ - + + + + + + + + + + + + + + + + + + diff --git a/src/android/FileTransfer.java b/src/android/FileTransfer.java index c04c0d3..c757c99 100644 --- a/src/android/FileTransfer.java +++ b/src/android/FileTransfer.java @@ -76,6 +76,7 @@ public class FileTransfer extends CordovaPlugin { public static int INVALID_URL_ERR = 2; public static int CONNECTION_ERR = 3; public static int ABORTED_ERR = 4; + public static int NOT_MODIFIED_ERR = 5; private static HashMap activeRequests = new HashMap(); private static final int MAX_BUFFER_SIZE = 16 * 1024; @@ -712,11 +713,11 @@ public class FileTransfer extends CordovaPlugin { File file = null; PluginResult result = null; TrackingInputStream inputStream = null; + boolean cached = false; OutputStream outputStream = null; try { OpenForReadResult readResult = null; - outputStream = resourceApi.openOutputStream(targetUri); file = resourceApi.mapUriToFile(targetUri); context.targetFile = file; @@ -764,78 +765,91 @@ public class FileTransfer extends CordovaPlugin { } connection.connect(); - - if (connection.getContentEncoding() == null || connection.getContentEncoding().equalsIgnoreCase("gzip")) { - // Only trust content-length header if we understand - // the encoding -- identity or gzip - if (connection.getContentLength() != -1) { - progress.setLengthComputable(true); - progress.setTotal(connection.getContentLength()); - } - } - inputStream = getInputStream(connection); - } - - try { - synchronized (context) { - if (context.aborted) { - return; - } - context.connection = connection; - } - - // write bytes to file - byte[] buffer = new byte[MAX_BUFFER_SIZE]; - int bytesRead = 0; - while ((bytesRead = inputStream.read(buffer)) > 0) { - outputStream.write(buffer, 0, bytesRead); - // Send a progress event. - progress.setLoaded(inputStream.getTotalRawBytesRead()); - PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject()); - progressResult.setKeepCallback(true); - context.sendPluginResult(progressResult); - } - } finally { - synchronized (context) { - context.connection = null; - } - safeClose(inputStream); - safeClose(outputStream); - } - - Log.d(LOG_TAG, "Saved file: " + target); - - // create FileEntry object - Class webViewClass = webView.getClass(); - PluginManager pm = null; - try { - Method gpm = webViewClass.getMethod("getPluginManager"); - pm = (PluginManager) gpm.invoke(webView); - } catch (NoSuchMethodException e) { - } catch (IllegalAccessException e) { - } catch (InvocationTargetException e) { - } - if (pm == null) { - try { - Field pmf = webViewClass.getField("pluginManager"); - pm = (PluginManager)pmf.get(webView); - } catch (NoSuchFieldException e) { - } catch (IllegalAccessException e) { - } - } - FileUtils filePlugin = (FileUtils) pm.getPlugin("File"); - if (filePlugin != null) { - JSONObject fileEntry = filePlugin.getEntryForFile(file); - if (fileEntry != null) { - result = new PluginResult(PluginResult.Status.OK, fileEntry); + if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { + cached = true; + connection.disconnect(); + Log.d(LOG_TAG, "Resource not modified: " + source); + JSONObject error = createFileTransferError(NOT_MODIFIED_ERR, source, target, connection, null); + result = new PluginResult(PluginResult.Status.ERROR, error); } else { - JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection, null); - Log.e(LOG_TAG, "File plugin cannot represent download path"); - result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error); + if (connection.getContentEncoding() == null || connection.getContentEncoding().equalsIgnoreCase("gzip")) { + // Only trust content-length header if we understand + // the encoding -- identity or gzip + if (connection.getContentLength() != -1) { + progress.setLengthComputable(true); + progress.setTotal(connection.getContentLength()); + } + } + inputStream = getInputStream(connection); + } + } + + if (!cached) { + try { + synchronized (context) { + if (context.aborted) { + return; + } + context.connection = connection; + } + + // write bytes to file + byte[] buffer = new byte[MAX_BUFFER_SIZE]; + int bytesRead = 0; + outputStream = resourceApi.openOutputStream(targetUri); + while ((bytesRead = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, bytesRead); + // Send a progress event. + progress.setLoaded(inputStream.getTotalRawBytesRead()); + PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject()); + progressResult.setKeepCallback(true); + context.sendPluginResult(progressResult); + } + } finally { + synchronized (context) { + context.connection = null; + } + safeClose(inputStream); + safeClose(outputStream); + } + + Log.d(LOG_TAG, "Saved file: " + target); + + + // create FileEntry object + Class webViewClass = webView.getClass(); + PluginManager pm = null; + try { + Method gpm = webViewClass.getMethod("getPluginManager"); + pm = (PluginManager) gpm.invoke(webView); + } catch (NoSuchMethodException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) { + } + if (pm == null) { + try { + Field pmf = webViewClass.getField("pluginManager"); + pm = (PluginManager)pmf.get(webView); + } catch (NoSuchFieldException e) { + } catch (IllegalAccessException e) { + } + } + file = resourceApi.mapUriToFile(targetUri); + context.targetFile = file; + FileUtils filePlugin = (FileUtils) pm.getPlugin("File"); + if (filePlugin != null) { + JSONObject fileEntry = filePlugin.getEntryForFile(file); + if (fileEntry != null) { + result = new PluginResult(PluginResult.Status.OK, fileEntry); + } else { + JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection, null); + Log.e(LOG_TAG, "File plugin cannot represent download path"); + result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error); + } + } else { + Log.e(LOG_TAG, "File plugin not found; cannot save downloaded file"); + result = new PluginResult(PluginResult.Status.ERROR, "File plugin not found; cannot save downloaded file"); } - } else { - Log.e(LOG_TAG, "File plugin not found; cannot save downloaded file"); - result = new PluginResult(PluginResult.Status.ERROR, "File plugin not found; cannot save downloaded file"); } } catch (FileNotFoundException e) { @@ -854,7 +868,6 @@ public class FileTransfer extends CordovaPlugin { Log.e(LOG_TAG, error.toString(), e); result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error); } finally { - safeClose(outputStream); synchronized (activeRequests) { activeRequests.remove(objectId); } @@ -872,7 +885,7 @@ public class FileTransfer extends CordovaPlugin { result = new PluginResult(PluginResult.Status.ERROR, createFileTransferError(CONNECTION_ERR, source, target, connection, null)); } // Remove incomplete download. - if (result.getStatus() != PluginResult.Status.OK.ordinal() && file != null) { + if (!cached && result.getStatus() != PluginResult.Status.OK.ordinal() && file != null) { file.delete(); } context.sendPluginResult(result); diff --git a/src/windows/FileTransferProxy.js b/src/windows/FileTransferProxy.js new file mode 100644 index 0000000..ba474a4 --- /dev/null +++ b/src/windows/FileTransferProxy.js @@ -0,0 +1,283 @@ +/* + * + * 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. + * +*/ + +/*jshint -W030 */ + +var FileTransferError = require('./FileTransferError'), + ProgressEvent = require('org.apache.cordova.file.ProgressEvent'), + FileUploadResult = require('org.apache.cordova.file.FileUploadResult'), + FileEntry = require('org.apache.cordova.file.FileEntry'); + + +// Some private helper functions, hidden by the module +function cordovaPathToNative(path) { + // turn / into \\ + var cleanPath = path.replace(/\//g, '\\'); + // turn \\ into \ + cleanPath = cleanPath.replace(/\\\\/g, '\\'); + // strip end \\ characters + cleanPath = cleanPath.replace(/\\+$/g, ''); + return cleanPath; +} + +function nativePathToCordova(path) { + var cleanPath = path.replace(/\\/g, '/'); + return cleanPath; +} + +var fileTransferOps = []; + +function FileTransferOperation(state, promise) { + this.state = state; + this.promise = promise; +} + +FileTransferOperation.PENDING = 0; +FileTransferOperation.DONE = 1; +FileTransferOperation.CANCELLED = 2; + + +module.exports = { + +/* +exec(win, fail, 'FileTransfer', 'upload', +[filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]); +*/ + upload:function(successCallback, errorCallback, options) { + var filePath = cordovaPathToNative(options[0]); + var server = options[1]; + var fileKey = options[2] || 'source'; + var fileName = options[3]; + var mimeType = options[4]; + var params = options[5]; + var trustAllHosts = options[6]; // todo + var chunkedMode = options[7]; // todo + var headers = options[8] || {}; + var uploadId = options[9]; + + if (filePath === null || typeof filePath === 'undefined') { + errorCallback && errorCallback(FileTransferError.FILE_NOT_FOUND_ERR); + return; + } + + if (String(filePath).substr(0, 8) == "file:///") { + filePath = Windows.Storage.ApplicationData.current.localFolder.path + String(filePath).substr(8).split("/").join("\\"); + } + + // Create internal download operation object + fileTransferOps[uploadId] = new FileTransferOperation(FileTransferOperation.PENDING, null); + + Windows.Storage.StorageFile.getFileFromPathAsync(filePath).then(function (storageFile) { + + if(!fileName) { + fileName = storageFile.name; + } + if(!mimeType) { + // use the actual content type of the file, probably this should be the default way. + // other platforms probably can't look this up. + mimeType = storageFile.contentType; + } + + storageFile.openAsync(Windows.Storage.FileAccessMode.read).then(function (stream) { + + // check if upload isn't already cancelled + var uploadOp = fileTransferOps[uploadId]; + if (uploadOp && uploadOp.state == FileTransferOperation.CANCELLED) { + // Here we should call errorCB with ABORT_ERR error + errorCallback && errorCallback(new FileTransferError(FileTransferError.ABORT_ERR, filePath, server)); + return; + } + + var blob = MSApp.createBlobFromRandomAccessStream(mimeType, stream); + + var formData = new FormData(); + formData.append(fileKey, blob, fileName); + // add params + for(var key in params) { + formData.append(key,params[key]); + } + + var uploadOperation; + try { + // Create XHR promise for uploading data to server + uploadOperation = WinJS.xhr({ type: "POST", url: server, data: formData, headers: headers }); + fileTransferOps[uploadId].promise = uploadOperation; + } catch (e) { + // it will fail if URL is malformed, so we handle this situation + errorCallback && errorCallback(new FileTransferError(FileTransferError.INVALID_URL_ERR, filePath, server, null, null, e)); + return; + } + + uploadOperation.then(function (response) { + storageFile.getBasicPropertiesAsync().done(function(basicProperties) { + var ftResult = new FileUploadResult(basicProperties.size, response.status, response.responseText); + successCallback && successCallback(ftResult); + }); + }, function(err) { + if ('status' in err) { + errorCallback && errorCallback(new FileTransferError(FileTransferError.CONNECTION_ERR, filePath, server, err.status, err.responseText, err)); + } else { + errorCallback && errorCallback(new FileTransferError(FileTransferError.INVALID_URL_ERR, filePath, server, null, null, err)); + } + }, function(evt) { + // progress event handler, calls successCallback with empty ProgressEvent + // We can't specify ProgressEvent data here since evt not provides any helpful information + var progressEvent = new ProgressEvent('progress'); + successCallback && successCallback(progressEvent, { keepCallback: true }); + }); + }); + }, function(err) { + errorCallback && errorCallback(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR, server, server, null, null, err)); + }); + }, + + download:function(successCallback, errorCallback, options) { + var source = options[0]; + var target = cordovaPathToNative(options[1]); + var downloadId = options[3]; + var headers = options[4] || {}; + + + if (target === null || typeof target === undefined) { + errorCallback && errorCallback(FileTransferError.FILE_NOT_FOUND_ERR); + return; + } + if (String(target).substr(0, 8) == "file:///") { + target = Windows.Storage.ApplicationData.current.localFolder.path + String(target).substr(8).split("/").join("\\"); + } + var path = target.substr(0, String(target).lastIndexOf("\\")); + var fileName = target.substr(String(target).lastIndexOf("\\") + 1); + if (path === null || fileName === null) { + errorCallback && errorCallback(FileTransferError.FILE_NOT_FOUND_ERR); + return; + } + + var download = null; + + // Create internal download operation object + fileTransferOps[downloadId] = new FileTransferOperation(FileTransferOperation.PENDING, null); + + Windows.Storage.StorageFolder.getFolderFromPathAsync(path).then(function (storageFolder) { + storageFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.generateUniqueName).then(function (storageFile) { + + // check if download isn't already cancelled + var downloadOp = fileTransferOps[downloadId]; + if (downloadOp && downloadOp.state == FileTransferOperation.CANCELLED) { + // Here we should call errorCB with ABORT_ERR error + errorCallback && errorCallback(new FileTransferError(FileTransferError.ABORT_ERR, source, target)); + return; + } + + // if download isn't cancelled, contunue with creating and preparing download operation + var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader(); + for (var header in headers) { + downloader.setRequestHeader(header, headers[header]); + } + + // create download object. This will throw an exception if URL is malformed + try { + var uri = Windows.Foundation.Uri(source); + download = downloader.createDownload(uri, storageFile); + } catch (e) { + // so we handle this and call errorCallback + errorCallback && errorCallback(new FileTransferError(FileTransferError.INVALID_URL_ERR)); + return; + } + + var downloadOperation = download.startAsync(); + // update internal TransferOperation object with newly created promise + fileTransferOps[downloadId].promise = downloadOperation; + + downloadOperation.then(function () { + + // Update TransferOperation object with new state, delete promise property + // since it is not actual anymore + var currentDownloadOp = fileTransferOps[downloadId]; + if (currentDownloadOp) { + currentDownloadOp.state = FileTransferOperation.DONE; + currentDownloadOp.promise = null; + } + + successCallback && successCallback(new FileEntry(storageFile.name, storageFile.path)); + }, function (error) { + + var result; + // Handle download error here. If download was cancelled, + // message property will be specified + if (error.message == 'Canceled') { + result = new FileTransferError(FileTransferError.ABORT_ERR, source, target, null, null, error); + } else { + // in the other way, try to get response property + var response = download.getResponseInformation(); + if (!response) { + result = new FileTransferError(FileTransferError.CONNECTION_ERR, source, target); + } else if (response.statusCode == 401 || response.statusCode == 404) { + result = new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR, source, target, response.statusCode, null, error); + } + } + + // Update TransferOperation object with new state, delete promise property + // since it is not actual anymore + var currentDownloadOp = fileTransferOps[downloadId]; + if (currentDownloadOp) { + currentDownloadOp.state = FileTransferOperation.CANCELLED; + currentDownloadOp.promise = null; + } + + // Cleanup, remove incompleted file + storageFile.deleteAsync().then(function () { + errorCallback && errorCallback(result); + }); + + + }, function(evt) { + + var progressEvent = new ProgressEvent('progress', { + loaded: evt.progress.bytesReceived, + total: evt.progress.totalBytesToReceive, + target: evt.resultFile + }); + progressEvent.lengthComputable = true; + + successCallback && successCallback(progressEvent, { keepCallback: true }); + }); + }, function (error) { + errorCallback && errorCallback(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR, source, target, null, null, error)); + }); + }, function (error) { + errorCallback && errorCallback(new FileTransferError(FileTransferError.FILE_NOT_FOUND_ERR, source, target, null, null, error)); + }); + }, + + abort: function (successCallback, error, options) { + var fileTransferOpId = options[0]; + + // Try to find transferOperation with id specified, and cancel its' promise + var currentOp = fileTransferOps[fileTransferOpId]; + if (currentOp) { + currentOp.state = FileTransferOperation.CANCELLED; + currentOp.promise && currentOp.promise.cancel(); + } + } + +}; + +require("cordova/exec/proxy").add("FileTransfer",module.exports); diff --git a/tests/plugin.xml b/tests/plugin.xml new file mode 100644 index 0000000..0830c4a --- /dev/null +++ b/tests/plugin.xml @@ -0,0 +1,30 @@ + + + + + Cordova File Transfer Plugin Tests + Apache 2.0 + + + + diff --git a/test/tests.js b/tests/tests.js similarity index 95% rename from test/tests.js rename to tests/tests.js index 1e198a6..7f0a5bd 100644 --- a/test/tests.js +++ b/tests/tests.js @@ -121,7 +121,7 @@ exports.defineAutoTests = function () { }; var getMalformedUrl = function () { - if (cordova.platformId === 'android') { + if (cordova.platformId === 'android' || cordova.platformId === 'amazon-fireos') { // bad protocol causes a MalformedUrlException on Android return "httpssss://example.com"; } else { @@ -240,7 +240,7 @@ exports.defineAutoTests = function () { }); it("filetransfer.spec.7 should be able to download a file using file:// (when hosted from file://)", function (done) { var downloadFail = createFail(done, "Download error callback should not have been called"); - var remoteFile = window.location.href.replace(/\?.*/, '').replace(/ /g, '%20'); + var remoteFile = window.location.protocol + '//' + window.location.pathname.replace(/ /g, '%20'); localFileName = remoteFile.substring(remoteFile.lastIndexOf('/') + 1); var lastProgressEvent = null; @@ -874,36 +874,9 @@ exports.defineManualTests = function (contentEl, createActionButton) { results.innerHTML = ''; } - function downloadImgCDV(ev) { - ev.preventDefault(); - ev.stopPropagation(); - downloadImg(imageURL, function (entry) { return entry.toURL(); }, new Image()); - } - - function downloadImgNative(ev) { - ev.preventDefault(); - ev.stopPropagation(); - downloadImg(imageURL, function (entry) { return entry.toNativeURL(); }, new Image); - } - - function downloadVideoCDV(ev) { - ev.preventDefault(); - ev.stopPropagation(); - var videoElement = document.createElement('video'); - videoElement.controls = "controls"; - downloadImg(videoURL, function (entry) { return entry.toURL(); }, videoElement); - } - - function downloadVideoNative(ev) { - ev.preventDefault(); - ev.stopPropagation(); - var videoElement = document.createElement('video'); - videoElement.controls = "controls"; - downloadImg(videoURL, function (entry) { return entry.toNativeURL(); }, videoElement); - } - - function downloadImg(source, urlFn, element) { + function downloadImg(source, urlFn, element, directory) { var filename = source.substring(source.lastIndexOf("/") + 1); + filename = directory + filename || filename; function download(fileSystem) { var ft = new FileTransfer(); console.log("Starting download"); @@ -919,39 +892,64 @@ exports.defineManualTests = function (contentEl, createActionButton) { clearResults(); requestFileSystem(TEMPORARY, 0, function (fileSystem) { console.log("Checking for existing file"); - fileSystem.root.getFile(filename, { create: false }, function (entry) { - console.log("Removing existing file"); - entry.remove(function () { + if (directory != undefined) { + console.log("Checking for existing directory."); + fileSystem.root.getDirectory(directory, {}, function (dirEntry) { + dirEntry.removeRecursively(function () { + download(fileSystem); + }, function (e) { console.log("ERROR: dirEntry.removeRecursively") }); + }, function () { download(fileSystem); - }, function (e) { console.log("ERROR: entry.remove"); }); - }, function () { - download(fileSystem); - }); + }); + } else { + fileSystem.root.getFile(filename, { create: false }, function (entry) { + console.log("Removing existing file"); + entry.remove(function () { + download(fileSystem); + }, function (e) { console.log("ERROR: entry.remove"); }); + }, function () { + download(fileSystem); + }); + } }, function (e) { console.log("ERROR: requestFileSystem"); }); } /******************************************************************************/ + var file_transfer_tests = '

Image File Transfer Tests

' + + '

The following tests should display an image of the Apache feather in the status box

' + + '
' + + '
' + + '
' + + '

Video File Transfer Tests

' + + '

The following tests should display a video in the status box. The video should play when play is pressed

' + + '
' + + '
'; + contentEl.innerHTML = '
' + - '
'; + file_transfer_tests; createActionButton('Download and display img (cdvfile)', function () { downloadImg(imageURL, function (entry) { return entry.toURL(); }, new Image()); - }, 'actions'); + }, 'cdv_image'); createActionButton('Download and display img (native)', function () { downloadImg(imageURL, function (entry) { return entry.toNativeURL(); }, new Image); - }, 'actions'); + }, 'native_image'); + + createActionButton('Download to a non-existent dir (should work)', function () { + downloadImg(imageURL, function (entry) { return entry.toURL(); }, new Image, '/nonExistentDirTest/'); + }, 'non-existent_dir'); createActionButton('Download and play video (cdvfile)', function () { var videoElement = document.createElement('video'); videoElement.controls = "controls"; downloadImg(videoURL, function (entry) { return entry.toURL(); }, videoElement); - }, 'actions'); + }, 'cdv_video'); createActionButton('Download and play video (native)', function () { var videoElement = document.createElement('video'); videoElement.controls = "controls"; downloadImg(videoURL, function (entry) { return entry.toNativeURL(); }, videoElement) - }, 'actions'); + }, 'native_video'); }; diff --git a/www/FileTransfer.js b/www/FileTransfer.js index d842c5a..ff4bbef 100644 --- a/www/FileTransfer.js +++ b/www/FileTransfer.js @@ -32,24 +32,23 @@ function newProgressEvent(result) { return pe; } +function getUrlCredentials(urlString) { + var credentialsPattern = /^http\:\/\/((.*?)\:(.*?))@.*$/g, + credentials = credentialsPattern.exec(urlString); + + return credentials && credentials[1]; +} + function getBasicAuthHeader(urlString) { var header = null; + + // This is changed due to MS Windows doesn't support credentials in http uris + // so we detect them by regexp and strip off from result url + // Proof: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/a327cf3c-f033-4a54-8b7f-03c56ba3203f/windows-foundation-uri-security-problem + if (window.btoa) { - // parse the url using the Location object - var url = document.createElement('a'); - url.href = urlString; - - var credentials = null; - var protocol = url.protocol + "//"; - var origin = protocol + url.host.replace(":" + url.port, ""); // Windows 8 (IE10) append :80 or :443 to url.host - - // check whether there are the username:password credentials in the url - if (url.href.indexOf(origin) !== 0) { // credentials found - var atIndex = url.href.indexOf("@"); - credentials = url.href.substring(protocol.length, atIndex); - } - + var credentials = getUrlCredentials(urlString); if (credentials) { var authHeader = "Authorization"; var authHeaderValue = "Basic " + window.btoa(credentials); @@ -97,6 +96,8 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro var httpMethod = null; var basicAuthHeader = getBasicAuthHeader(server); if (basicAuthHeader) { + server = server.replace(getUrlCredentials(server) + '@', ''); + options = options || {}; options.headers = options.headers || {}; options.headers[basicAuthHeader.name] = basicAuthHeader.value; @@ -125,7 +126,7 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro } var fail = errorCallback && function(e) { - var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body); + var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body, e.exception); errorCallback(error); }; @@ -157,6 +158,8 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro var basicAuthHeader = getBasicAuthHeader(source); if (basicAuthHeader) { + source = source.replace(getUrlCredentials(source) + '@', ''); + options = options || {}; options.headers = options.headers || {}; options.headers[basicAuthHeader.name] = basicAuthHeader.value; @@ -191,7 +194,7 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro }; var fail = errorCallback && function(e) { - var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body); + var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body, e.exception); errorCallback(error); }; diff --git a/www/FileTransferError.js b/www/FileTransferError.js index 1394f59..07ca831 100644 --- a/www/FileTransferError.js +++ b/www/FileTransferError.js @@ -23,17 +23,19 @@ * FileTransferError * @constructor */ -var FileTransferError = function(code, source, target, status, body) { +var FileTransferError = function(code, source, target, status, body, exception) { this.code = code || null; this.source = source || null; this.target = target || null; this.http_status = status || null; this.body = body || null; + this.exception = exception || null; }; FileTransferError.FILE_NOT_FOUND_ERR = 1; FileTransferError.INVALID_URL_ERR = 2; FileTransferError.CONNECTION_ERR = 3; FileTransferError.ABORT_ERR = 4; +FileTransferError.NOT_MODIFIED_ERR = 5; module.exports = FileTransferError; 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); diff --git a/www/windows8/FileTransferProxy.js b/www/windows8/FileTransferProxy.js deleted file mode 100644 index d72e985..0000000 --- a/www/windows8/FileTransferProxy.js +++ /dev/null @@ -1,143 +0,0 @@ -/* - * - * 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 FileTransferError = require('./FileTransferError'), - FileUploadResult = require('org.apache.cordova.file.FileUploadResult'), - FileEntry = require('org.apache.cordova.file.FileEntry'); - -module.exports = { - -/* -exec(win, fail, 'FileTransfer', 'upload', -[filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]); -*/ - upload:function(successCallback, error, options) { - var filePath = options[0]; - var server = options[1]; - var fileKey = options[2] || 'source'; - var fileName = options[3]; - var mimeType = options[4]; - var params = options[5]; - var trustAllHosts = options[6]; // todo - var chunkedMode = options[7]; // todo - var headers = options[8] || {}; - - if (filePath === null || typeof filePath === 'undefined') { - error && error(FileTransferError.FILE_NOT_FOUND_ERR); - return; - } - - if (String(filePath).substr(0, 8) == "file:///") { - filePath = Windows.Storage.ApplicationData.current.localFolder.path + String(filePath).substr(8).split("/").join("\\"); - } - - Windows.Storage.StorageFile.getFileFromPathAsync(filePath).then(function (storageFile) { - - if(!fileName) { - fileName = storageFile.name; - } - if(!mimeType) { - // use the actual content type of the file, probably this should be the default way. - // other platforms probably can't look this up. - mimeType = storageFile.contentType; - } - - storageFile.openAsync(Windows.Storage.FileAccessMode.read).then(function (stream) { - - - var blob = MSApp.createBlobFromRandomAccessStream(mimeType, stream); - - var formData = new FormData(); - formData.append(fileKey, blob, fileName); - // add params - for(var key in params) { - formData.append(key,params[key]); - } - - WinJS.xhr({ type: "POST", url: server, data: formData, headers: headers }).then(function (response) { - storageFile.getBasicPropertiesAsync().done(function (basicProperties) { - - Windows.Storage.FileIO.readBufferAsync(storageFile).done(function (buffer) { - var dataReader = Windows.Storage.Streams.DataReader.fromBuffer(buffer); - var fileContent = dataReader.readString(buffer.length); - dataReader.close(); - var ftResult = new FileUploadResult(); - ftResult.bytesSent = basicProperties.size; - ftResult.responseCode = response.status; - ftResult.response = fileContent; - successCallback && successCallback(ftResult); - }); - - }); - }, function () { - error && error(FileTransferError.INVALID_URL_ERR); - }); - }); - - },function() { - error && error(FileTransferError.FILE_NOT_FOUND_ERR); - }); - }, - - download:function(successCallback, error, options) { - var source = options[0]; - var target = options[1]; - var headers = options[4] || {}; - - - if (target === null || typeof target === undefined) { - error && error(FileTransferError.FILE_NOT_FOUND_ERR); - return; - } - if (String(target).substr(0, 8) == "file:///") { - target = Windows.Storage.ApplicationData.current.localFolder.path + String(target).substr(8).split("/").join("\\"); - } - var path = target.substr(0, String(target).lastIndexOf("\\")); - var fileName = target.substr(String(target).lastIndexOf("\\") + 1); - if (path === null || fileName === null) { - error && error(FileTransferError.FILE_NOT_FOUND_ERR); - return; - } - - var download = null; - - - Windows.Storage.StorageFolder.getFolderFromPathAsync(path).then(function (storageFolder) { - storageFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.generateUniqueName).then(function (storageFile) { - var uri = Windows.Foundation.Uri(source); - var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader(); - - for (var header in headers) { - downloader.setRequestHeader(header, headers[header]); - } - download = downloader.createDownload(uri, storageFile); - download.startAsync().then(function () { - successCallback && successCallback(new FileEntry(storageFile.name, storageFile.path)); - }, function () { - error && error(FileTransferError.INVALID_URL_ERR); - }); - }); - }); - } -}; - -require("cordova/exec/proxy").add("FileTransfer",module.exports);