[ 
https://issues.apache.org/jira/browse/CB-2787?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13683354#comment-13683354
 ] 

Gregor Gabriel edited comment on CB-2787 at 10/22/13 8:01 AM:
--------------------------------------------------------------

This is the Java code for =downloader.js=

{code:javascript}
cordova.define("cordova/plugin/downloader",
  function(require, exports, module) {
    var exec = require("cordova/exec");

    var Downloader = function() {};

    /**
    * 
    */
    Downloader.prototype.downloadFile = function(fileUrl, params, win, fail) {

        function base64Encode(str) {
            var CHARS = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
            var out = "", i = 0, len = str.length, c1, c2, c3;
            while (i < len) {
                c1 = str.charCodeAt(i++) & 0xff;
                if (i == len) {
                    out += CHARS.charAt(c1 >> 2);
                    out += CHARS.charAt((c1 & 0x3) << 4);
                    out += "==";
                    break;
                }
                c2 = str.charCodeAt(i++);
                if (i == len) {
                    out += CHARS.charAt(c1 >> 2);
                    out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
                    out += CHARS.charAt((c2 & 0xF) << 2);
                    out += "=";
                    break;
                }
                c3 = str.charCodeAt(i++);
                out += CHARS.charAt(c1 >> 2);
                out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
                out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
                out += CHARS.charAt(c3 & 0x3F);
            }
            return out;
        }
        
        function load_binary_resource(url) {
                var req = new XMLHttpRequest();
                req.open('GET', url, false);
                //XHR binary charset opt by Marcus Granado 2006 
[http://mgran.blogspot.com]
                req.overrideMimeType('text\/plain; charset=x-user-defined');
                req.send(null);
                if (req.status != 200) {
                        console.log("unable to load " + fileUrl);
                        fail();
                        return null;
                }
                if (req.response === null) {
                        fail();
                        return null;
                }
                return req.response;
        }

        console.log("start loading " + fileUrl);
        
        var base64File = base64Encode(load_binary_resource(fileUrl));
        
        //Make params hash optional.
        if (!fail) win = params;
        PhoneGap.exec(win, fail, "Downloader", "downloadFile", [base64File, 
params]);

        fileUrl = null;
                base64File = null;

    };
    

    var downloader = new Downloader();
    module.exports = downloader;
});


if (!window.plugins) {
    window.plugins = {};
}
if (!window.plugins.downloader) {
    window.plugins.downloader = cordova.require("cordova/plugin/downloader");
}

{code}

And this is the Java code of Downloader.java

{code:java}
package com.phonegap.plugins.downloader;

import java.io.File;
import java.io.FileOutputStream;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;

import android.util.Base64;


public class Downloader extends CordovaPlugin {
        
    private CallbackContext context;

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action        The action to execute.
     * @param args          JSONArry of arguments for the plugin.
     * @param callbackId    The callback id used when calling back into 
JavaScript.
     * @return              A PluginResult object with a status and message.
     */
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext 
callbackContext) throws JSONException {

        this.context = callbackContext;
        
                if (!action.equals("downloadFile")) {
            this.context.sendPluginResult(new 
PluginResult(PluginResult.Status.INVALID_ACTION, "Plugin Downloader cannot 
handle action "+action));
                return true;
                }
                try {
                        
                        //String fileUrl = args.getString(0);
                        //byte[] fileContent = Base64.decode( 
params.getString("fileUrl"), Base64.DEFAULT );
                        byte[] fileContent = Base64.decode( args.getString(0), 
Base64.DEFAULT );
                        
                        JSONObject params = args.getJSONObject(1);
                        
                        String fileName = params.getString("fileName");
                        
                        String dirName =params.getString("dirName");
                        
                        Boolean overwrite = params.has("overwrite") ? 
params.getBoolean("overwrite") : false;
                        
                        
this.context.sendPluginResult(this.downloadUrl(fileContent, dirName, fileName, 
overwrite));
                        fileContent = null;
                        params = null;
            return true;
                        
                } catch (JSONException e) {

                        e.printStackTrace();
                        
                        this.context.sendPluginResult(new 
PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage()));
                return true;

                } catch (InterruptedException e) {
                        e.printStackTrace();
                        
                        this.context.sendPluginResult(new 
PluginResult(PluginResult.Status.ERROR, e.getMessage()));
                        return true;
                }
        
        }

        private PluginResult downloadUrl(byte[] fileUrl, String dirName, String 
fileName, Boolean overwrite) throws InterruptedException, JSONException {
        
                try {
                        System.gc();

                        Log.d("Downloader", "write file " + dirName + "/" + 
fileName);
                        
                        dirName = dirName.replace("file:///", "/");
                        
                        File dir = new File(dirName);
                        if (!dir.exists()) {
                                dir.mkdirs();
                        }
                        
                        File file = new File(dirName, fileName);
                        
                        if (!overwrite && file.exists()) {
                                Log.d("Downloader", "File already exist");
                                
                                JSONObject obj = new JSONObject();
                                obj.put("status", 1);
                                obj.put("total", 0);
                                obj.put("file", fileName);
                                obj.put("dir", dirName);
                                obj.put("progress", 100);
                                
                                return new PluginResult(PluginResult.Status.OK, 
obj);
                        }
                        
                        int progress = 0;
                        int fileSize = 0;
                
                        FileOutputStream fos = null;
                                
                        try {
                                // Log.d("Downloader", "Download starts, 
connection is open ...");

                                fos = new FileOutputStream(file);
                                fos.write(fileUrl);
                                //fos.close();
                                //fos = null;
                                //fileUrl = null;
                                
                        } catch (Exception e){
                                Log.e("Downloader", e.getMessage());
                        } finally {
                                try {
                                        fos.close();
                                        fos = null;
                                        fileUrl = null;
                                    //Log.d("Downloader","closed input stream 
output stream and connection");
                                    
                                        JSONObject obj = new JSONObject();
                                        obj.put("status", 1);
                                        obj.put("total", fileSize);
                                        obj.put("file", fileName);
                                        obj.put("dir", dirName);
                                        obj.put("progress", progress);
                                        
                                        return new 
PluginResult(PluginResult.Status.OK, obj);
                                    
                                } catch ( Exception e) {
                                        fos = null;
                                        fileUrl = null;
                                        Log.w("Downloader","Fehler beim 
Aufraeumen - "+e.getStackTrace().toString() );
                                }
            }

                        //Log.d("Downloader", "Download finished");

                        JSONObject obj = new JSONObject();
                        obj.put("status", 1);
                        obj.put("total", fileSize);
                        obj.put("file", fileName);
                        obj.put("dir", dirName);
                        obj.put("progress", progress);
                        
                        return new PluginResult(PluginResult.Status.OK, obj);
                        
                }
                finally {
                        // do nothing           
                }
        }

}
{code}

the usage ot the plugin is:

{code:javascript}
                try {
                        dir="/a/path/to/a/directory/no/ending/slash";
                        file"a_file.name";
                        window.onLoaded=function(){
                            console.log("do something here, when download 
succeded");
                        }
                        window.onError=function(){
                            console.log("do something here, when download 
failed");
                        }
                        url = 
"https://issues.apache.org/jira/secure/projectavatar?pid=12312420&avatarId=15888&size=large";;
                        window.plugins.downloader.downloadFile(
                                url,
                                {overwrite: true,
                                dirName: dir,
                                fileName: file}, 
                                onLoaded,
                                onError
                        );
                }
                catch (e) {
                        // do some error handling
                }
{code}



was (Author: ggabriel):
This is the Java code for =downloader.js=

{code:javascript}
cordova.define("cordova/plugin/downloader",
  function(require, exports, module) {
    var exec = require("cordova/exec");

    var Downloader = function() {};

    /**
    * 
    */
    Downloader.prototype.downloadFile = function(fileUrl, params, win, fail) {

        function base64Encode(str) {
            var CHARS = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
            var out = "", i = 0, len = str.length, c1, c2, c3;
            while (i < len) {
                c1 = str.charCodeAt(i++) & 0xff;
                if (i == len) {
                    out += CHARS.charAt(c1 >> 2);
                    out += CHARS.charAt((c1 & 0x3) << 4);
                    out += "==";
                    break;
                }
                c2 = str.charCodeAt(i++);
                if (i == len) {
                    out += CHARS.charAt(c1 >> 2);
                    out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
                    out += CHARS.charAt((c2 & 0xF) << 2);
                    out += "=";
                    break;
                }
                c3 = str.charCodeAt(i++);
                out += CHARS.charAt(c1 >> 2);
                out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
                out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
                out += CHARS.charAt(c3 & 0x3F);
            }
            return out;
        }
        
        function load_binary_resource(url) {
                var req = new XMLHttpRequest();
                req.open('GET', url, false);
                //XHR binary charset opt by Marcus Granado 2006 
[http://mgran.blogspot.com]
                req.overrideMimeType('text\/plain; charset=x-user-defined');
                req.send(null);
                if (req.status != 200) {
                        console.log("unable to load " + fileUrl);
                        fail();
                        return null;
                }
                if (req.response === null) {
                        fail();
                        return null;
                }
                return req.response;
        }

        console.log("start loading " + fileUrl);
        
        var base64File = base64Encode(load_binary_resource(fileUrl));
        
        //Make params hash optional.
        if (!fail) win = params;
        PhoneGap.exec(win, fail, "Downloader", "downloadFile", [base64File, 
params]);

        fileUrl = null;
                base64File = null;

    };
    

    var downloader = new Downloader();
    module.exports = downloader;
});


if (!window.plugins) {
    window.plugins = {};
}
if (!window.plugins.downloader) {
    window.plugins.downloader = cordova.require("cordova/plugin/downloader");
}

{code}

And this is the Java code of Downloader.java

{code:java}
package com.phonegap.plugins.downloader;

import java.io.File;
import java.io.FileOutputStream;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;

import android.util.Base64;


public class Downloader extends CordovaPlugin {
        
    private CallbackContext context;

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action        The action to execute.
     * @param args          JSONArry of arguments for the plugin.
     * @param callbackId    The callback id used when calling back into 
JavaScript.
     * @return              A PluginResult object with a status and message.
     */
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext 
callbackContext) throws JSONException {

        this.context = callbackContext;
        
                if (!action.equals("downloadFile")) {
            this.context.sendPluginResult(new 
PluginResult(PluginResult.Status.INVALID_ACTION, "Plugin Downloader cannot 
handle action "+action));
                return true;
                }
                try {
                        
                        //String fileUrl = args.getString(0);
                        //byte[] fileContent = Base64.decode( 
params.getString("fileUrl"), Base64.DEFAULT );
                        byte[] fileContent = Base64.decode( args.getString(0), 
Base64.DEFAULT );
                        
                        JSONObject params = args.getJSONObject(1);
                        
                        String fileName = params.getString("fileName");
                        
                        String dirName =params.getString("dirName");
                        
                        Boolean overwrite = params.has("overwrite") ? 
params.getBoolean("overwrite") : false;
                        
                        
this.context.sendPluginResult(this.downloadUrl(fileContent, dirName, fileName, 
overwrite));
                        fileContent = null;
                        params = null;
            return true;
                        
                } catch (JSONException e) {

                        e.printStackTrace();
                        
                        this.context.sendPluginResult(new 
PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage()));
                return true;

                } catch (InterruptedException e) {
                        e.printStackTrace();
                        
                        this.context.sendPluginResult(new 
PluginResult(PluginResult.Status.ERROR, e.getMessage()));
                        return true;
                }
        
        }

        private PluginResult downloadUrl(byte[] fileUrl, String dirName, String 
fileName, Boolean overwrite) throws InterruptedException, JSONException {
        
                try {
                        System.gc();

                        Log.d("Downloader", "write file " + dirName + "/" + 
fileName);
                        
                        dirName = dirName.replace("file:///", "/");
                        
                        File dir = new File(dirName);
                        if (!dir.exists()) {
                                dir.mkdirs();
                        }
                        
                        File file = new File(dirName, fileName);
                        
                        if (!overwrite && file.exists()) {
                                Log.d("Downloader", "File already exist");
                                
                                JSONObject obj = new JSONObject();
                                obj.put("status", 1);
                                obj.put("total", 0);
                                obj.put("file", fileName);
                                obj.put("dir", dirName);
                                obj.put("progress", 100);
                                
                                return new PluginResult(PluginResult.Status.OK, 
obj);
                        }
                        
                        int progress = 0;
                        int fileSize = 0;
                
                        FileOutputStream fos = null;
                                
                        try {
                                // Log.d("Downloader", "Download starts, 
connection is open ...");

                                fos = new FileOutputStream(file);
                                fos.write(fileUrl);
                                //fos.close();
                                //fos = null;
                                //fileUrl = null;
                                
                        } catch (Exception e){
                                Log.e("Downloader", e.getMessage());
                        } finally {
                                try {
                                        fos.close();
                                        fos = null;
                                        fileUrl = null;
                                    //Log.d("Downloader","closed input stream 
output stream and connection");
                                    
                                        JSONObject obj = new JSONObject();
                                        obj.put("status", 1);
                                        obj.put("total", fileSize);
                                        obj.put("file", fileName);
                                        obj.put("dir", dirName);
                                        obj.put("progress", progress);
                                        
                                        return new 
PluginResult(PluginResult.Status.OK, obj);
                                    
                                } catch ( Exception e) {
                                        fos = null;
                                        fileUrl = null;
                                        Log.w("Downloader","Fehler beim 
Aufraeumen - "+e.getStackTrace().toString() );
                                }
            }

                        //Log.d("Downloader", "Download finished");

                        JSONObject obj = new JSONObject();
                        obj.put("status", 1);
                        obj.put("total", fileSize);
                        obj.put("file", fileName);
                        obj.put("dir", dirName);
                        obj.put("progress", progress);
                        
                        return new PluginResult(PluginResult.Status.OK, obj);
                        
                }
                finally {
                        // do nothing           
                }
        }

}
{code}

the usage ot the plugin is:

{code:javascript}
                try {
                        url = 
"https://issues.apache.org/jira/secure/projectavatar?pid=12312420&avatarId=15888&size=large";;
                        window.plugins.downloader.downloadFile(
                                url.replace(/ /g,'%20'),
                                {overwrite: true,
                                dirName: dir,
                                fileName: file}, 
                                onLoaded,
                                onError
                        );
                }
                catch (e) {
                        // do some error handling
                }
{code}


> PhoneGap FileTransfer.Download more than 300 files
> --------------------------------------------------
>
>                 Key: CB-2787
>                 URL: https://issues.apache.org/jira/browse/CB-2787
>             Project: Apache Cordova
>          Issue Type: Bug
>          Components: Android
>    Affects Versions: 2.5.0
>            Reporter: Cho
>            Assignee: Ian Clelland
>
> I had tried to download more than 300 files and then it hit error after that. 
> Seems like some IO Connection was not properly closed. I wrote a small code 
> to test it out. 
> Any idea? How to file a report or get a source of phonegap to check the real 
> cause?
> {code}
> var counter = 500;
> function DownloadFile() {
>         if (counter == 0) {
>             DownloadComplete();
>             return;
>         }
>         var ft = new FileTransfer();
>         var downloadUrl = "<source>";
>         var dlPath = "<target>"
>         ft.download(downloadUrl, dlPath, function(entry) {
>             counter--;
>             UpdateProgress();
>             DownloadFile();
>         }, function(error) {
>             DownloadFailed();
>         }, true);
>     }
> {code}
> note: <target> and <source> is alright because it was it failed when the 
> counter goes until 300+.
> {code}
> 03-14 08:35:09.706: E/FileTransfer(24867): 
> {"target":"<target>","source":"<source>","http_status":200,"code":1}
> 03-14 08:35:09.706: E/FileTransfer(24867): java.io.FileNotFoundException: 
> <source>: open failed: EMFILE (Too many open files)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> libcore.io.IoBridge.open(IoBridge.java:416)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> java.io.FileOutputStream.<init>(FileOutputStream.java:88)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> java.io.FileOutputStream.<init>(FileOutputStream.java:73)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> org.apache.cordova.FileTransfer$4.run(FileTransfer.java:685)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> java.lang.Thread.run(Thread.java:856)
> 03-14 08:35:09.706: E/FileTransfer(24867): Caused by: 
> libcore.io.ErrnoException: open failed: EMFILE (Too many open files)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> libcore.io.Posix.open(Native Method)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
> 03-14 08:35:09.706: E/FileTransfer(24867):     at 
> libcore.io.IoBridge.open(IoBridge.java:400)
> 03-14 08:35:09.706: E/FileTransfer(24867):     ... 6 more
> {code}



--
This message was sent by Atlassian JIRA
(v6.1#6144)

Reply via email to