Phonegap android plugin for download files from url on sd card

[UPDATE]
You can found an updated version of my plugin on GitHub
Thanks to Phillip Neumann.
—————————————

Hi folks, today I want to share with you this very useful phonegap‘s plug-in.
As the title says this plug-in allow you to download a file (url) on the sd card in the folder of your choice.

Usage

downloader.downloadFile(fileUrl,dirName,fileName,overwrite,win,fail);

Params

fileUrl: <String> The url of the file to download
dirName: <String> The directory where you want to save the file
fileName: <String> The name of the file
overwrite: <Boolean> Overwrite the file if exist
win: <Function> Success callback function. Receive a parameter that contains the fileName if the file is wrote with success.  If the overwrite parameter is false and the file already exist the parameter will contain the string “exist”.
fail: <Function> Fail callback function. Receive a parameter that contains the error message

Source and installation

Like all phonegap android plugins is composed by tha java file and the javascript one.
For starting using this plugin first copy the java file into the java src folder of your android project, in my example  the package is called com.example.pgplugins.DownloaderPlugin.

File: Downloader.java

package com.example.pgplugins.downloaderPlugin;

/*
 @author Mauro Rocco http://www.toforge.com
*/

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

import android.util.Log;

import com.phonegap.DroidGap;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class Downloader extends Plugin{

 @Override
 public PluginResult execute(String action, JSONArray args, String callbackId) {
 if (action.equals("downloadFile")) {
 try {
 return this.downloadUrl(args.getString(0),args.getString(1),args.getString(2),args.getString(3));
 } catch (JSONException e) {
 return new PluginResult(PluginResult.Status.ERROR, "Param errrors");
 }
 }
 else {
 return new PluginResult(PluginResult.Status.INVALID_ACTION);
 }

 }

 private PluginResult downloadUrl(String fileUrl, String dirName, String fileName, String overwrite){
 try{
 Log.d("DownloaderPlugin", "DIRECTORY CALLED /sdcard/"+dirName+" created");
 File dir =     new File("/sdcard/"+dirName);
 if(!dir.exists()){
 Log.d("DownloaderPlugin", "directory /sdcard/"+dirName+" created");
 dir.mkdirs();
 }

 File file = new File("/sdcard/"+dirName+fileName);

 if(overwrite.equals("false") && file.exists()){
 Log.d("DownloaderPlugin", "File already exist");
 return new PluginResult(PluginResult.Status.OK, "exist");
 }

 URL url = new URL(fileUrl);
 HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
 ucon.setRequestMethod("GET");
 ucon.setDoOutput(true);
 ucon.connect();

 Log.d("DownloaderPlugin", "download begining");

 Log.d("DownloaderPlugin", "download url:" + url);

 InputStream is = ucon.getInputStream();

 byte[] buffer = new byte[1024];

 int len1 = 0;

 FileOutputStream fos = new FileOutputStream(file);

 while ( (len1 = is.read(buffer)) > 0 ) {
 fos.write(buffer,0, len1);
 }

 fos.close();

 Log.d("DownloaderPlugin", "Download complete in" + fileName);

 } catch (IOException e) {

 Log.d("DownloaderPlugin", "Error: " + e);
 return new PluginResult(PluginResult.Status.ERROR, "Error: " + e);

 }

 return new PluginResult(PluginResult.Status.OK, fileName);

 }

}

Now copy the following javascript file in the assets/www folder, remember to change the name of the package or the js will never found the java file.

File: downloader.js

function Downloader() {

}

Downloader.prototype.downloadFile = function(fileUrl,dirName,fileName,overwrite,win,fail) {
 if(overwrite==false) overwrite="false";
 else overwrite="true";
 PhoneGap.exec(win, fail, "Downloader", "downloadFile", [fileUrl,dirName,fileName,overwrite]);

};

PhoneGap.addConstructor(function() {
 PhoneGap.addPlugin("downloader", new Downloader());
 PluginManager.addService("Downloader","com.example.pgplugins.downloaderPlugin.Downloader");
});

For use it you have only to include the js file in the page and call it in this way

<script type="text/javascript" charset="utf-8" src="downloader.js"></script>
 <script type="text/javascript">

 window.plugins.downloader.downloadFile("http://www.toforge.com/archive.zip","sdcard/cache/","archive.zip", false,
 function(data){
 if(data=="exist"){
 alert("File already exist");
 }
 else{
 alert("File saved on sd card")
 }
 },function(data){ alert("error: "+data); });

 </script>

If you like it please jut say me “thanks” or send me 100000 € :-D .
See you on the next post

This entry was posted in Android and tagged , , , , , . Bookmark the permalink.
  • Mauro Rocco

    Please paste your code on pastie.org and leave a comment with the link.

  • Vikas

    Thanks, but no money ;-)

  • rolimat

    Hi!! The plugin doesnt work. Im using phonegap 1.1.0. I’ve read on the phonegap wiki that since version 1.1.0 Plugin Manager has been deleted so your plugin has this error.

    I removed the line where the plugin is added to Plugin Manager but, there is one more error. Eclipse debugger says to me:

    Functions.js (js file where I do calls to downloader): Uncaught TypeError: Cannot call method ‘downloadFile’ of undefined

    Phonegap-1.1.0.js: Line 770: Error in success callback: Network Status1 = TypeError: Cannot set property

    Can you help me?? Thank yo so much!!

  • Mauro Rocco

    The code in this post is old, here you found an updated version of my plugin that works with the new phonegap https://github.com/purplecabbage/phonegap-plugins/tree/master/Android/Downloader

  • stesic74

    Hi Mauro,
    my compliments for the plugin.
    Unfortunately, I think you must consider 2 important issues.
    First, at line 39, you write “sdcard/download” as default folder, but it’s a relative path. It’s better to write the absolute path “/sdcard/download”. Without initial slash, I found problems to write files on my tablet.
    Second, “/sdcard” is not always the root of the sdcard and I correct your code using Environment.getExternalStorageDirectory() :)

    Bye,
    Stefano

  • Mauro Rocco

    As already said, this plugin refer to a very old version of phonegap, I strongly suggest to look at the updated version on github.
    Bye

  • Xavi

    Hey, I have the same error as rollmat. I’ve downloaded the latest version form GitHub (August 2011) and PhoneGap 1.2 and It isn’t working.

    aLogcat from eclipse return this error:

    TypeError: Result of expression ‘window.plugins.downloader’ [undefined] is not an object. at file:///android_asset/www/index.html:11

    I’m trying to download a txt file from a web and read It in JS.

    Thanks!

  • baton

    THANKS

  • mohit

    Thanks

  • Irshad

    Hi,
    I am new to Android i have doubt
    whats the usage of the below line ? Is actually needed ?

    PluginManager.addService(“Downloader”,”com.example.pgplugins.downloaderPlugin.Downloader”);

  • http://pmg.com.vn huy_vn

    I didn’t run your plugin
    Logcat from eclipse return this error:

    ReferenceError: Can’t find variable: PhoneGap at file:///android_asset/www/downloader.js:15
    can you give me source code example of you. or help me check my source code at
    http://www.mediafire.com/?k0k9l6c264y8yyz
    thank you

  • Lkman

    I tried the plugin out but i get “class not found” error. please help.

  • Raj

    Will the above code also work on Blackberry?

  • Mauro Rocco

    @Raj This code will not work on BB. Sorry

  • http://edso212.com Edso

    Ijin Download Brooo… :)
    Thanks

  • Pingback: PhoneGap: download & save binary files (mp3s) for iPhone & Android

  • Ganesh

    Using the downloader creates a new session. How can the session be maintained since authentication is already done.

  • Greg

    Is there a way to handle downloading from a url such as:

    http://domain.com/fileDownload.ashx?fileName=Test.pdf

    Where contents are like:

    // set return content type
    Response.AddHeader("content-disposition", "inline; filename=\"" + fileName + ".PDF\"");
    Response.ContentType = "application/pdf";

    // return file to page
    byte[] data = memoryStream.ToArray();
    Response.OutputStream.Write(data, 0, data.Length);

  • Dmitriy

    Hello.
    I found a little error: Environment variable cannot be found, so we must add a row in the top of Java file:
    import android.os.*;

    I’m not sure how to commit this change, so please do it yourself.

  • ysony

    thank your very many!

  • Terry

    Thank a lot!

  • Olusola

    Hi Mauro,

    Please I am trying to rewrite this as a plugin for uploading instead.

    I am pretty new to java and not too sure how to proceed.

    Would appreciate any pointers. I know that its possible to use the upload method in fileTransfer from file API, but I would like to display the progress bar while the transfer is going on.

    Thanks.

  • Vipin Garg

    Hello,
    I have a problem when i am using this plugin that value sdcard/cache/ at 1 of type java.lang.String can not be converted to JSONObject..
    Can you tell me why this problem is coming, i just changed the assetURL?

  • Mirko

    Hi, your pluginsdoesnt work on my Samsung Galaxy S2 (Android 4.0.3 official) , while it works on the same device with Android 2.2.
    I get open failed EACCESS (Permission denied)

    Thanks in advance,
    Mirko

  • Mirko

    cancel my comment, I modified my permission and now work also on ICS

  • Marjan

    Hi,

    This plugin obviously doesn’t work on cordova-2.0.0.js! I’m having this problem: 11-01 21:54:13.675: E/Web Console(14059): Uncaught TypeError: Cannot read property ‘downloader’ of undefined at file:///android_asset/www/scripts/network.js:3535

    I followed everything to the letter but it’s the same.
    Need help!

  • Marjan

    Update:
    If you closely observe the LogCat log, you will notice that there is an error in “downloader.js” file. It is made for older version of phonegap. I was searching a lot how to fix the same problem as yours but I only found this question.
    So, the bottom line is that we’ll have to fix the syntax in the script file. Those morons changed whole syntax without care of backward compatibility :(
    Now I’m asking, does anyone know how to fix this problem? :)

  • larsbx

    Nice job! Very helpful, thank you… :)

  • eduard

    @Marjan

    Try this in you downloader.js:

    Downloader.prototype.downloadFile = function(fileUrl, params, win, fail) {
    //Make params hash optional.
    if (!fail) win = params;

    return cordova.exec(
    win,
    fail,
    “Downloader”,
    “downloadFile”,
    [fileUrl, params]
    );

    };

    cordova.addConstructor(function() {
    window.downloader = new Downloader();

    // backwards compatibility
    window.plugins = window.plugins || {};
    window.plugins.downloader = window.downloader;
    });

  • vinod

    very nice

  • Nurun Naher

    hi I am facing same problem. already read all the comments and solution here. but doesnt solved yet. Have your problem was solved ? plz help

  • Nurun Naher

    Hi,

    This plugin obviously doesn’t work on cordova-2.9.0.js! I’m having this problem:Uncaught TypeError: Cannot read property ‘downloader’ of undefined

    I followed everything to the letter but it’s the same.
    Need help!