Friday, December 30, 2011

On the Sixth Day of PhoneGapping: Downloading a File

Did you know that the FileTransfer object got a new download method in PhoneGap 1.3.0? You didn't, well thanks to Alexander Heinrich for spurring it's  development and getting it checked in for Android and iOS (download is also available to you BlackBerry users). Finally PhoneGap developers have a convenient way to download binary files.

The method signature is:
download(source, destination, successCallback, errorCallback);
Where the parameters are:

source: The URL you want to download
destination: The full file path you want the file stored at
successCallback: called with a FileEntry object that represents the new file
errorCallback: called when something goes wrong

So say we want to download a PNG image and store it on the SD card. Well you'd write some code that looks like this:

16 comments:

GIACOPINO said...

Hi,

I've juste copy/paste your sample code, but it doesn't work

I'm running phonegap 1.3.0

2012-01-05 20:17:05.842 FileAssets[37881:13403] [INFO] >>> onDeviceReady
2012-01-05 20:17:05.843 FileAssets[37881:13403] File Transfer downloading file...
2012-01-05 20:17:06.943 FileAssets[37881:18a03] Write file /ics.png
2012-01-05 20:17:06.945 FileAssets[37881:13403] File Transfer Error: http://developer.android.com/assets/images/home/ics-android.png
2012-01-05 20:17:06.948 FileAssets[37881:13403] [INFO] download error source http://developer.android.com/assets/images/home/ics-android.png
2012-01-05 20:17:06.948 FileAssets[37881:13403] [INFO] download error target /ics.png
2012-01-05 20:17:06.949 FileAssets[37881:13403] [INFO] upload error code2

Can you help me?

Simon MacDonald said...

@GIACOPINO

Do you have an SD Card? Do you have write external down as one of your permissions in your AndroidManifest.xml?

GIACOPINO said...

Hi simon

I'm on IOs...

Simon MacDonald said...

Right so if you just copy and paste my code you won't have a "/sdcard". You should remove that bit from the sample and try again.

GIACOPINO said...

Hi again this is what i've done is you look at the output :

2012-01-05 20:17:06.943 FileAssets[37881:18a03] Write file /ics.png

I've also whitelist all url by "*"

I've tried :

path = '/ics.png' and path='ics.png' and always the same error

Tks for your help

Simon MacDonald said...

I'm not really the iOS expert. You should come over to the PhoneGap Google Group and ask your question.

GIACOPINO said...

Done :
http://groups.google.com/group/phonegap/browse_thread/thread/7c3674b92587c9d0

Unknown said...

in that part of my html I paste this code?

Simon MacDonald said...

@By_JPSP

Yes, you just call that JavaScript code when you want to download a file.

lamakun said...

I am getting an error dealing with fileTransfer. Its code is 1 which is "File not found error" but I don't know whether the problem is the remote file (which is a correct url as i test it in my browsers and shows the image I want to download) or the target file.

The target file does not exists but I assume it should create it when downloading with the given name int the file path.

I have added the following tags to my config.xml (phonegap build):




So I allow the app to connect to any url.

I also tried the link given by GIACOPINO but dind't don it either. My current code is:

function downloadImg(){
alert("downloadImg");
/* var fileTransfer = new FileTransfer();
fileTransfer.download(
"http://www.mytests.es/wp-content/plugins/sitepress-multilingual-cms/res/flags/es.png",
"/sdcard/liv-apks/es.png",
function(theFile) {
alert("download complete: " + theFile.toURI());
alert(theFile.toURI());
showLink(theFile.toURI());
},
function(error) {
alert("download error source " + error.source);
alert("download error target " + error.target);
alert("upload error code: " + error.code);
},
true
);*/
try{
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
function(fileSystem){
var rootPath = fileSystem.root.fullPath;
alert(">>>rootPath = "+rootPath);
var fileTransfer = new FileTransfer();
fileTransfer.download(
"http://www.mytests.es/wp-content/plugins/sitepress-multilingual-cms/res/flags/es.png",
rootPath+'/es.png',
function(entry) {
alert("download complete: " + entry.fullPath);
},
function(error) {
alert("download error source " + error.source);
alert("download error target " + error.target);
alert("upload error code" + error.code);
}
);
}, null);
}catch(err){
alert(err.message);
}
}

Anyone can give a hand?

Thanks!!!

Simon MacDonald said...

@lamakun

Make it "file:///sdcard/liv-apks/es.png" and make sure the directory /sdcard/liv-apks exists.

lamakun said...

Thank you very much Simon. I found out what the problem was and it was related to the permissions I had given the app in config.xml. I had been playing with them to check how it works and apparently I was avoiding the app to download contents (still haven't checked out which is the permission that controls it, I am on it right now).


Thank you very much!!

Simon MacDonald said...

@lamakun

You were probably missing WRITE_EXTERNAL_STORAGE.

lamakun said...

Hi again Simon,

all of a sudden I find myself in a new problem that is keeping me stuck for hours. I have the following code:

function wait(){
$(document).ready(
function() {
document.addEventListener("deviceready", init(), true);
}
);
}

Where "wait" is a javscript function called from the onload event. I use the onload event, as well as $(document).ready and "deviceready" event to make sure every single thing is loaded when i start coding.

The "init()" method does a few things and then calls the following method:

function download_img(imgToDownload){
var url = remote_url+imgToDownload;
try{
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
function (fs) {
var imagePath = fs.root.fullPath +"/"+ imgToDownload; // full file path
var fileTransfer = new FileTransfer();
fileTransfer.download(url, imagePath,
function (entry) {
alert("OK: " + entry.fullPath); // entry is fileEntry object
},
function (error) {
alert("download error source " + error.source);
alert("download error target " + error.target);
alert("upload error code" + error.code);
alert("http_status"+error.http_status);
}
);
}
);
}catch(err){ alert(err.message); } }

Where I get the error message: "LocalFileSystem is not defined".

My config.xml is:




PhoneGap Build Application

A simple PhoneGap Build application.


Your Name








In case I might add any permission, even though I think right now I have them all. It is happening to me in Android 2.3.3, and I don't know whether it might work fine in some other devices, but anyhow I need it to work in all Android/iOS devices. Do you have any idea why I am getting this error?

Thanks Simon!!

Simon MacDonald said...

@lamakun

It isn't:

document.addEventListener("deviceready", init(), true);

it should be:

document.addEventListener("deviceready", init, true);

having the () after init calls that function immediately before the deviceready event is fired.

lamakun said...

Thanks Simon, we can keep on in stackoverflow so it might help more people ok?

Thank you very much!!!