Manage Files In Android And iOS Using IonicFramework

You may one day find yourself needing to make an IonicFramework Android and iOS app that downloads media or in-app purchase content from a remote web server to the users device.  Maybe you created an audio app that plays music from the cloud and you decided to cache upcoming songs in your playlist like Google Music does.  This will involve downloading the media files to your device in the background so it is ready to go.

Lucky for us, Apache Cordova has a set of File APIs that we can use in our Ionic project for exactly this.

Let’s start by creating a fresh IonicFramework project with the Android and iOS platforms included.

Please remember that if you are not using a Mac, you cannot add the iOS platform.

The next thing we want to do is add the Apache Cordova file plugin into our project.  We can add it to our project by running the following:

The file plugin is quite large, so we’re only going to focus on the following items:

  • Creating and loading directories
  • Creating and loading files
  • Downloading files from remote servers

To start things off, open your www/js/app.js file and include the FileController seen below:

The focus of this tutorial will be loading files and downloading files.  File and directory creation will be included in the process.

Let’s start by working with the download() method.  It will create a directory if it doesn’t already exist, and then create a fresh file space.  The remote file will then be downloaded into this fresh file space on the devices local file system.

The above code will download remote image ionic-logo-blog.png and save it to /ExampleProject/test.png.  You can get as fancy as you want with this function, but for simplicity I am just calling the file test.png.

The next thing we need to worry about is the load() method which will behave very similar to the download() method.  It just never actually downloads anything and has no write permissions.

Nothing new was introduced in the load() method that didn’t already exist in the download() method.  If you wanted to fancy up your code you could do a lot of optimizations to what I provided.  For example, you could pull out all the nested functions and make them re-usable in your controller.  I’ll leave it to you to be inventive.

Now that we have two methods for managing images, we should probably present them to the screen.  In your www/index.html file, add the following code:

In the above code, you’ll notice that the highlighted section contains the stuff that I changed.  Everything else is just stock IonicFramework.  The UI will have two buttons, one for downloading and one for loading.  When pressed, a loading message will display until the image has processed.  Then the image path and image will display on the screen.

A video version of this article can be seen below.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

  • naeem

    Thanks , Awesome Post , how would you do this with a video file.

    • This post was only intended to demonstrate files in general. Not focus on a specific type of file.

      I have video coming in a different post.

      Regards,

  • Markus

    thanks for the code, it is very useful example. However, i have spent a couple of days, and cannot get it working?? The error is always the same: LocalFileSystem is not defined.

    I have tried so many variations, different syntax, searched every forum online, but cannot find a solution. Have you ever encountred this problem, do you know how to fix it??

    Also, can the filesystem functions only be tested in an emulator or on a device? or can it be done in the browser too.

    Any advice would be greatly appreciated, as i am going nuts here.

  • oidacra

    Excelent!!

  • Himanshu

    Hi Nic !!!

    what i can do with code…when multiple image retrieve from the phone folder ???

  • Himanshu

    ok…i got it !!!
    create another dirEntry.getFile() for
    dirEntry.getFile(
    “android-1.jpg”,
    {
    create: false,
    exclusive: false
    },
    function gotFileEntry(fe) {
    $ionicLoading.hide();
    $scope.imgFile1 = fe.toURL();
    },
    function(error) {
    $ionicLoading.hide();
    console.log(“Error getting file”);
    }
    );

    but ….there is method to load all images from a folder without creating another dirEntry.getFile()???

    • Himanshu

      i want to put all images in array and show in slide with ng-repeat 😐

      • I suggest you make use of the DirectoryReader to list all files and directories in a specified directory.

        https://cordova.apache.org/docs/en/3.3.0/cordova_file_file.md.html#DirectoryReader

        Using that command inside a custom AngularJS factory or service, you should be able to craft some logic for recursively scanning and reading all files at a given path.

        Also, please make sure you only post one comment with your question, not three. Makes it impossible for future readers to follow.

        Regards,

  • Elindor

    Hey Nic, thanks for the examples !

    I tried to do it with ngcordova, using something like

    $cordovaFileTransfer.download(“http://www.myserver.com/file.jpg”, “cdvfile://localhost/persistent/myapp/medias/myfile.jpg”)

    It works, when I use a file manager to get to the folder myapp/medias/ the image myfile.jpg is here, and I can open it on the gallery or whatever app I want to use to see images… But it won’t appear in the gallery nor in the Photos app (I’m on Android). For a basic user it’s disturbing : they don’t use file explorer and should not have to.

    Since you have experienced a lot with files download, do you have any idea of what I should do ?

    Thanks !

    • I don’t use ngCordova for this, so I cannot help you on that subject.

      As for photos appearing in the gallery, I thought they needed to be in a very specific directory on the device. I could be wrong though. I don’t often mess with photos or the gallery, but you might want to see if the gallery app can scan for photos on the device. Or maybe specify a folder where they exist.

      Regards,

  • Derek Hannah

    how would you just save a picture you took from a the camera instead of downloading from a url?

  • Mhabub

    Hello,
    Thanks for such a nice post.
    I have already implemented it based on your example code.
    it works fine in Android and file downloaded in my custom folder
    But in IOS it seems problem. I can not see downloaded file in IOS. Is there any permission if for IOS creating folder and downloading file?

    Thanks

    • Are there any error logs? Or do you have an appropriate file browser for viewing files on the SD in iOS?

  • great post nic,
    what would you advice me to do if i change the two buttons into one button, every thing will stay the same, only if you click download and there is a success, then the Button (the same button) text will change to Load and it will call the Load funschtion if you click on it.
    I have the same issue, i want to load a pdf file, and then i want to show it, but i want to use one Button instead of two, a Button that changes his text and ng-click function once you click on it (but only once), from download to Load, and if you start the app, it shows download again.
    Actulay i did that witn ng-show and ng-hide, it is complicated, but you might have a better solution.
    Tanks
    isaid

    • There are two approaches I would use:

      The solution you already tried with ng-show
      Have a scope variable that is boolean. When you click download, set it to true. Then change your method to accept this scope variable and decide what to do with a true or false value. You can also store the button text as a scope variable and update that accordingly in your function as well.

      Hopefully that gives you some insight.

      Regards,

      • thank you Ron for your reply, it works well.
        Regards

        • I’m glad you got it working!

          Also, thank you for your contribution to the blog. Helps me to pay for hosting to keep it running :-). I gave you a shoutout on Twitter too.

          • that is the minimum what we can do here to keep it going, you do a great job in your blog, beside the good documentation and examples on ionicframework, makes it easy for me to unterstand it, but i miss this on the angular side, specially a blog like yours, and the angular 2 confuses me and makes me not to be sure about which direction angular wants to go.

            What i found on the net for angular is a lot of schools that explain angular which i do not have access to only if i pay.

  • itgoujie2

    Thanks for the post, it works fine for me on IOS to save image to app’s folder, but how can I save to album? just give me targetPath would be very helpful, thanks

    • I’m not sure, but I think you’d have to use the camera API.

      Regards,

  • deepakgd

    I am getting image url from api, how to use this code for multiple images. i have tried but it was not wokring. my code is
    $scope.download = function(urlProduct,nameProduct) {
    $ionicLoading.show({
    template: ‘Loading…’
    });
    console.log(“inside”)
    console.log(urlProduct)
    console.log(nameProduct)
    document.addEventListener(“deviceready”, function() {
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fs) {
    console.log(“success”)
    fs.root.getDirectory(
    “pos”,
    {
    create: true
    },
    function(dirEntry) {
    console.log(“2inside”+” “+ nameProduct)
    dirEntry.getFile(
    nameProduct,
    {
    create: true,
    exclusive: false
    },
    function gotFileEntry(fe) {
    var p = fe.toURL();
    fe.remove();
    ft = new FileTransfer();
    ft.download(
    encodeURI(urlProduct),
    p,
    function(entry) {
    $ionicLoading.hide();
    $scope.imgFile = entry.toURL();
    },
    function(error) {
    $ionicLoading.hide();
    alert(“Download Error Source -> ” + error.source);
    },
    false,
    null
    );
    },
    function() {
    $ionicLoading.hide();
    console.log(“Get file failed”);
    }
    );
    }
    );
    },
    function() {
    $ionicLoading.hide();
    console.log(“Request for filesystem failed”);
    });
    }, false);

    Please help me

    • I don’t read large chunks of code in the comments section of the blog. You’ll have to put your code on Gist / GitHub and format it if you want me to look at it.

      On another note, what isn’t working? Are you getting errors? Is it causing your device to make noise? Is it telling you a joke? There are endless possibilities to “it is not working”. Please give me some thorough details.

      Regards,

      • deepakgd

        Your code working fine sir. I dont know how to use it for multiple image storage and access it. I am getting url from API i want to download it and access those image sir. Please help me sir.

        • Sounds like you probably want to write your own HTML parser. Parse requested HTML for URL links and then pass each link into the file management function for downloading.

          Regards,

  • Angelo Rigo

    Great tutorial! How do i implement the FileController as a factory or service? passing two parameters, a url and a name for a file that the url generates ? I will have many controllers each one with a url and a name for the generated file. Thanks

    • Yea, like I responded in your other comment, I would create a service that all controllers must go through in order to work with PDFs. That way there is one centralized system of control.

      Regards,

  • Rajesh d m

    Again, thanks for the very elaborate post ( i have been reading almost all your tutorial on IONIC)

    How can you just read and write to a file using ANGULAR and IONIC ? like just write take an input “hello” from the user and write it to a text file, and then be able to open that file and read data from it (TEXT File)?

    Thanks in advance

  • Tailesh Bamankar

    Hi,

    GALLERY DOES NOT SHOW THE IMAGE AFTER DOWNLOAD?
    But it show up respective path

    • This tutorial will not add images to your gallery. It will only download files to the filesystem.

      Regards,

      • Gattamaneni Venkatanarasimham

        K sir it is nice but i am having the format var Format=”

        Array of Strings

        “;
        How to download the Format form ft.download(……..

        • I have no idea what you’re trying to tell me.

          Regards,

  • Angelo Rigo

    Great tutorial! working fone for me! how can i call the load method just after the moment the download method finish ?

    • As seen in the tutorial, the FileTransfer.download method has a success callback. You can add it in there, but I don’t see why you would need to in this example because I already load it right after downloading.

      Regards,

      • Angelo Rigo

        Yes it works! i do add inApBrowser window.open inside the succesCalback. Based on the tutorial i implement it as a service, not sure why the load method is not called just after the download, i let my code on http://plnkr.co/edit/ASB7LSCuCRvVLGI3Kqxf?p=info

  • Patrk Comi

    how do i put the path we are downloading from in the view….. so i can change the url with an input field …??

    • I encourage you to read up a little on AngularJS. You would change the download function to accept an argument like:

      Then you would typically use ng-model in your front-end and call the function via a button press.

      Regards,

  • Adusumilli Seshachandra

    how to make the downloaded files not avaiIable to access from outside the app???

    • This is not possible. Any file you download using your application will be accessible to anyone who wishes to access it outside.

      Regards,

  • Hridaya Kandel

    thank u for simple and nicely explained example. i tried for everything is fine the folder is created but the image from url is not downloaded. no error seen in console.

    • Did you install the FileTransfer plugin? Are you trying to use this from ionic serve, ionic view, ionic live-reload, or phonegap build? If you are, don’t because none of those will work.

      I need your full error logs.

      Regards,

      • Hridaya Kandel

        i used run with genymotion.. some how its working now. i am working on getting request from user for different pdf files and download it to their device.. click on different buttons and download the files.. what could be best way to do this..

      • Hridaya Kandel

        I use run and genymotion.. i got this in my log..
        0 944856 log Error in Success callbackId: File934061943 : ReferenceError: FileTransfer is not defined
        1 944857 log processMessage failed: Error: ReferenceError: FileTransfer is not defined
        2 944865 log processMessage failed: Stack: ReferenceError: FileTransfer is not defined
        at gotFileEntry (http://192.168.56.1:8100/js/controllers.js:188:17)
        at win (http://192.168.56.1:8100/plugins/cordova-plugin-file/www/DirectoryEntry.js:109:9)
        at Object.cordova.callbackFromNative (http://192.168.56.1:8100/cordova.js:286:58)
        at processMessage (http://192.168.56.1:8100/cordova.js:1070:21)
        at Function.androidExec.processMessages (http://192.168.56.1:8100/cordova.js
        :1107:13)at pollOnce (http://192.168.56.1:8100/cordova.js:963:17)
        at pollOnceFromOnlineEvent (http://192.168.56.1:8100/cordova.js:953:5)
        3 944866 log processMessage failed: Message: S01 File934061943 {“isFi le”:true,”isDirectory”:false,”name”:”agrimagazine_ashar.pdf”,”fullPath”:”/AICC/agrimagazine_ashar.pdf”,”filesystemName”:”persistent”,”filesystem”:1,”nativeURL
        “:”file:///storage/emulated/0/AICC/agrimagazine_ashar.pdf”}

        • When I see an IP like “http://192.168.56.1:8100” it tells me you are not testing a packaged build. I’m guessing you’re using ionic serve, ionic view, ionic live-reload, or phonegap build, which I’m telling you will not work correctly with native plugins.

          Regards,

          • Hridaya Kandel

            i am using “ionic run android -c -l”
            with genymotion installed and checking the file in file manager… it stuck on loading….. and i saw above logs in console.

          • the “-l” is live-reload. Don’t use it.

            Do this:

          • Hridaya Kandel

            i did the same even installed apk in device the screen stucks in loading.. how can i view my error with above.

          • Hridaya Kandel

            It still says filetransfer not defined

            D/CordovaLog( 1944): file:///android_asset/www/cordova.js: Line 305 : Error in S uccess callbackId: File919978153 : ReferenceError: FileTransfer is not defined I/chromium( 1944): [INFO:CONSOLE(305)] “Error in Success callbackId: File9199781 53 : ReferenceError: FileTransfer is not defined”, source: file:///android_asset /www/cordova.js (305) D/CordovaLog( 1944): file:///android_asset/www/cordova.js: Line 1075 : processMe ssage failed: Error: ReferenceError: FileTransfer is not defined I/chromium( 1944): [INFO:CONSOLE(1075)] “processMessage failed: Error: Reference Error: FileTransfer is not defined”, source: file:///android_asset/www/cordova.j s (1075) D/CordovaLog( 1944): file:///android_asset/www/cordova.js: Line 1076 : processMe ssage failed: Stack: ReferenceError: FileTransfer is not defined D/CordovaLog( 1944): at gotFileEntry (file:///android_asset/www/js/controlle rs.js:188:17) D/CordovaLog( 1944): at win (file:///android_asset/www/plugins/cordova-plugi n-file/www/DirectoryEntry.js:109:9) D/CordovaLog( 1944): at Object.cordova.callbackFromNative (file:///android_a sset/www/cordova.js:286:58) D/CordovaLog( 1944): at processMessage (file:///android_asset/www/cordova.js :1070:21) D/CordovaLog( 1944): at Function.androidExec.processMessages (file:///androi d_asset/www/cordova.js:1107:13) D/CordovaLog( 1944): at pollOnce (file:///android_asset/www/cordova.js:963:1 7) D/CordovaLog( 1944): at pollOnceFromOnlineEvent (file:///android_asset/www/c ordova.js:953:5) I/chromium( 1944): [INFO:CONSOLE(1076)] “processMessage failed: Stack: Reference Error: FileTransfer is not defined I/chromium( 1944): at gotFileEntry (file:///android_asset/www/js/controllers .js:188:17) I/chromium( 1944): at win (file:///android_asset/www/plugins/cordova-plugin- file/www/DirectoryEntry.js:109:9) I/chromium( 1944): at Object.cordova.callbackFromNative (file:///android_ass et/www/cordova.js:286:58) I/chromium( 1944): at processMessage (file:///android_asset/www/cordova.js:1 070:21) I/chromium( 1944): at Function.androidExec.processMessages (file:///android_ asset/www/cordova.js:1107:13) I/chromium( 1944): at pollOnce (file:///android_asset/www/cordova.js:963:17) I/chromium( 1944): at pollOnceFromOnlineEvent (file:///android_asset/www/cor dova.js:953:5)”, source: file:///android_asset/www/cordova.js (1076) I/Choreographer( 1944): Skipped 30 frames! The application may be doing too muc h work on its main thread. D/CordovaLog( 1944): file:///android_asset/www/cordova.js: Line 1077 : processMe ssage failed: Message: S01 File919978153 {“isFile”:true,”isDirectory”:false,”nam e”:”agrimagazine_ashar.pdf”,”fullPath”:”/AICC/agrimagazine_ashar.pdf”,”filesys temName”:”persistent”,”filesystem”:1,”nativeURL”:”file:///storage/emulated/ 0/AICC/agrimagazine_ashar.pdf”} I/chromium( 1944): [INFO:CONSOLE(1077)] “processMessage failed: Message: S01 Fil e919978153 {“isFile”:true,”isDirectory”:false,”name”:”agrimagazine_ashar.pdf”,”f ullPath”:”/AICC/agrimagazine_ashar.pdf”,”filesystemName”:”persistent”,”filesys tem”:1,”nativeURL”:”file:///storage/emulated/0/AICC/agrimagazine_ashar.pd f”}”, source: file:///android_asset/www/cordova.js (1077) I/Choreographer( 1944): Skipped 30 frames! The application may be doing too muc h work on its main thread.

          • Hridaya Kandel

            many thanks Nic finally i found in internet that suggested to install https://github.com/apache/cordova-plugin-file-transfer and its working now

          • Great! I’m glad you got it 🙂

  • Hridaya Kandel

    how do i view downloading status in notification bar.

    • You’re going to need a different plugin for that and unfortunately I don’t know of one.

      Regards,

  • Philip Baumgartner

    thank you for this example. it eases the start with the file transfer topic a lot. unfortunately the function keeps invoking the error callback (http_status 401 / error code 3) on my computer when i launch it on the android virtual device. i made sure there is a tag in the [project_folder]/config.xml and a in the [project_folder]/platforms/android/AndroidManifest.xml

    can you help?

    • Can you paste your full error logs?

      • Philip Baumgartner

        those i wrote are all i have. i got them from the error callback because i chaged it a little to;

        function(error) {
        $ionicLoading.hide();
        alert(“error code: ” + error.code + ” http_status: ” + error.http_status
        + ” online: ” + window.navigator.onLine);
        }

        how do i get more?

          • Philip Baumgartner

            ok it seems that it was because i copied your function into the project i am working on. when i strictly follow your formula, it works. maybe your debugging tutorial can help me find out the exact reason. so far, thank you very, very much for the quick response and these tutorials. perhaps they make me able to recover some free time this semester break 😀

          • Yea check to see if you have other errors firing in your code through ADB. Incredibly useful tool for testing.

  • Karthikeya Mishra

    I have used cordova.file.externalRootDirectory to create a folder. And I downloaded the photos in that folder. But now my problem is I want to check whether the file I am downloading already exist in that folder but I am unable to get the path of that folder.

    I am using Ionic framewrok. To download the image in folder I used –

    $scope.downloaad= function(photoUrl, photoId, folder){
    var url = photoUrl;
    var targetPath = cordova.file.externalRootDirectory+”/”+folder+”/”+photoId+”.jpg”;

    var trustHosts = true;
    var str = {};

    $cordovaFileTransfer.download(url, targetPath, str, trustHosts)
    .then(function(result) {
    console.log(“result->” + result);
    }, function(err) {
    console.log(“error->” + err);
    });

    }

  • pixculim

    Thnaks for the tutorial Nic, though I followed the tutorial several times I get an error after doing $ ionic serve “ReferenceError: LocalFileSystem is not defined” from reading on other sites i need to define the storing file structure first for each device??? Any help will be greatly appreciated..

  • Emile Esterhuizen

    Really useful article, it helped me a bunch, I’ve been trying to download a mp3 file and then access it again on iOS. I thought I’d just comment on one modification I made to the code. I changed line 27 in the download function from:

    $scope.imgFile = entry.toURL();

    to

    $scope.imgFile = entry.toInternalURL();

    toInternalURL() returns a url that looks something like this:
    cdvfile://…/ExampleProject/file.mp3,

    whereas toEntryURL() returns file:///…/ExampleProject.file.mp3

    and for some reason iOS won’t play audio files with the file:/// prefix

    … hope it helps someone.

  • Really useful article, but i get the error called :-

    LocalFileSystem is not defined

    why !!

    • How about sharing your full logs?

      Regards,

      • I try same your code and work, But the problem i cannot see PDF file, How can do that

        • What do you mean see PDF file? You cannot open it? It doesn’t exist? Something else?

          I need more information.

          Regards,

          • On your code you are talk about images ( encodeURI(“http://ionicframework.com/img/ionic-logo-blog.png”),) and i replace it by PDF to show it. How can do that ?

          • PDFs are not the same as images. They cannot just be displayed on a page like an image. In addition to this, not all flavors of Android can process PDF files without some external application.

            With that said, you’d only be able to download the PDF, not display it.

            Regards,

          • But i need to display PDF file, How can do that ? i see some tag like pdfviewer but not work with me

          • I personally don’t think that is possible, but it is a question probably better asked in the forums.

            Sorry,

    • Jaume

      I get the same error. It happens in my iPad with version 8.1.
      window.requestFileSystem does not exist and it crashes there.

      Though using the iOS emulator from xCode it works.

      Edit:
      Ok, I read more comments and I see I cannot use Iconic view dealing with native plugins.
      That sucks but good to know.
      Thanks!

      • Yep, all kinds of bugs with ionic serve, ionic view, and ionic live-reload. Save yourself some trouble and stay away from them.

        Best,

  • Kent Kawahara

    Hello Nic

    Thank you for the great article! However, when I tried to run your code on Genymotion, it gets stuck with $ionicLoading.
    Do you know what is wrong with the code? I simply copied and pasted your code and can’t seem to find what is going on. Perhaps something is wrong with genymotion

    • What do your logs say?

      • Kent Kawahara

        I’m sorry, I’ve seen your post about generating error logs. Let me run it again and I’ll update you.

  • Fares

    Is there a way to create files in a directory accessible by other apps (for example dowloads directory). Actually , I want to create a file with ionic app and then open it with fileopener plugin.

    • Yes anything written to the device SD storage can be accessed by any application. This tutorial might give you more insight:

      https://www.airpair.com/ionic-framework/posts/ionic-file-browser-app

      Best,

      • Fares

        Thanks
        I want it to work on any android or ios device, so sd card is not the right solution for me

      • Fares

        if there is no easy way to do that
        i will probably use that file browser tutorial to make the user choose where to store the file

  • Stevie Starosciak

    Hey there Nic,

    I really appreciate this tutorial. You have unlocked some sanity after spending countless hours trying to use the $cordovaFileTransfer default functionality…which when tested on android…it doesn’t download at all, so that’s always good.

    One thing I’m noticing is that, though this code works inside of the Ionic App viewer on android, when I load this up using the ios6 emulator, utilizing xCode 7.0.1, I hit “Download” and, though it gives me the filepath, it does NOT show the image (which it does on Android). Could this be an emulation issue with xCode? Would you have any insight as to why this would happening for ios specifically? Unfortunately, I don’t have an iphone to test this on, but if you had any insight, it’d be much appreciated 😀

    • Rule #1, don’t use ionic view, ionic serve, ionic live-reload, or phonegap build to test your application when working with native device plugins. These tools are all beta or alpha and are known to have a ton of problems with plugins.

      If you get past rule #1, let me know what your logs say and we’ll go from there 🙂

  • Stevie Starosciak

    Thanks for responding so quickly 🙂 I see. Hmm, well how should I test my application then? It would seem that trying to use ionic emulate android/ios -l -c -s is out of the picture. I get unpredictabe results when hopping between the Android, iOS, and Ionic View emulators. There are instances where the cordovaFileTransfer plugin works fine for both IOS and Android emulators, but then on Android Ionic View, it just sits there.

    I’m kind of at a loss, because I’m basically trying to download a zip file from a remote source, unzip that file, and then serve the contents of that file in an iframe (which is just a microwebsite for taking a course). I have the downloading of the zip and unzipping that file working in the emulators, but the iframe won’t show the contents :'(

    I don’t know which things to trust anymore haha

    What do you think?

    • Treat hybrid apps as if they were native apps. Don’t try to shortcut the development and testing process because it will bite you in the end.

      I cannot stress this enough. The ionic serve, ionic view, ionic live-reload, and phonegap build services should never be used.

      Best,

      • Stevie Starosciak

        Hah I just now noticed there is a “Reply” button under each comment. The good news…I got things working! I plug my android phone into my macbook, run “ionic run android” with “adb logcat” and all my functionality works, with error logging going on 🙂

        The last thing I’ll ask is…if this is the preferred development environment, does every single change require a re-run of the app? and is there any way to do any type of console.logging to look at responses from functions as JSON strings?

        Again, thanks for the help, you are quite the invaluable individual 🙂

  • Vamsi Krishna

    Hi nic,

    I hit “Download” and, though it gives me the filepath, it does NOT show the image. I am running on iphone6 phone(Personal).

    • What do your logs say?

      • Vamsi Krishna

        json data with nativeURL. Actually i want video url download to save iOS library. SO that i can make video available to all others app. I found that its impossible. Is it true ? Any other way to do it.

        • What do your logs say? You can post as many questions in my blog as you want, but you won’t get a different answer from me until I see your logs.

          Regards,

          • Vamsi Krishna

            {“isFile”:true,”isDirectory”:false,”name”:”CF22D6AD-390C-8AFA-763F-A72C8AD753F3.jpg”,”fullPath”:”/mavGram/CF22D6AD-390C-8AFA-763F-A72C8AD753F3.jpg”,”filesystem”:””,”nativeURL”:”file:///var/mobile/Containers/Data/Application/72826E52-7D5B-4377-BD31-C3A30E0A74B8/Library/files/mavGram/CF22D6AD-390C-8AFA-763F-A72C8AD753F3.jpg”}

            But image is not displaying in iOS library. SO other can access it. I want to download files same as whatsapp. Other apps can access this same file.

          • The tutorial I demonstrated is generic to all file types. It doesn’t care if it is an image or not. With that said, in its current form, other apps would need to use the exact file path if they wish to access the file. It will not be placed in the image, music, or video libraries.

  • Joenathan Prasetyo

    Hi nic…
    I have problem with this tutorial, I click the download button, but that happens only just loading popup

    this is my log:

    ReferenceError: LocalFileSystem is not defined
    at Scope.$scope.load (http://localhost:8100/js/app.js:76:30)
    at fn (eval at (http://localhost:8100/lib/ionic/js/ionic.bundle.js:21972:15), :4:203)
    at http://localhost:8100/lib/ionic/js/ionic.bundle.js:57514:9
    at Scope.$eval (http://localhost:8100/lib/ionic/js/ionic.bundle.js:24673:28)
    at Scope.$apply (http://localhost:8100/lib/ionic/js/ionic.bundle.js:24772:23)
    at HTMLButtonElement. (http://localhost:8100/lib/ionic/js/ionic.bundle.js:57513:13)
    at HTMLButtonElement.eventHandler (http://localhost:8100/lib/ionic/js/ionic.bundle.js:12098:21)
    at triggerMouseEvent (http://localhost:8100/lib/ionic/js/ionic.bundle.js:2865:7)
    at tapClick (http://localhost:8100/lib/ionic/js/ionic.bundle.js:2854:3)
    at HTMLDocument.tapMouseUp (http://localhost:8100/lib/ionic/js/ionic.bundle.js:2927:5)

    please help..

    • The http:/localhost:8100 in your logs tells me you are using ionic serve, ionic view, or ionic live-reload, all of which work pretty terrible when it comes to plugins. I suggest you build your application and then install it to a device or simulator rather than trying to serve it.

      Regards,

      • Joenathan Prasetyo

        after that I followed your advice to wear a device simulator, I type the command “ionic run android” why so error?

        • Well it says JAVA_HOME is not set, so you should probably do that.

          • Joenathan Prasetyo

            like this?
            C:Program FilesJavajdk1.8.0_51bin;C:Program FilesJavajre1.8.0_20

          • Not sure what you pasted. Is that your PATH? You need to set a JAVA_HOME. I am not a Windows person so I won’t be able to help with that one.

            Sorry,

  • Shrikant

    hii nic thanx for this tutorial,
    i want to move my ionic app in external device but move to sd-card option are disable how to i create my ionic app which can i move on sd-card, i try this android:installLocation=”preferExternal” or android:installLocation=”auto” in
    file AndroidManifest.xml find it on myappplatformsandroidbuildintermediatesmanifestsfulldebug but after build app this line (android:installLocation=”preferExternal”) automatically remove and i can not move myapp in sd-card please help me what i do for move my ionic app in sd-card.

  • Indika Ratnayake

    Hi Nic, Excellent video. I also watched the video you posted on airpair (https://www.airpair.com/ionic-framework/posts/ionic-file-browser-app) and this question is regarding that. I followed all the steps you described and the app runs but does not display any file list only the header can be seen. I went through the logcat messages but couldn’t resolve the issue. Could you please help me to resolve this issue. Thanks in advance.

    • I see a cannot find method error in that screenshot. Please paste the logs next time rather than using screenshots.

  • Indika Ratnayake

    Hi Nic,

    I thought I replied to your comment, but I guess it wasn’t posted. This is the full log. Really appreciate your help. Thanks.

    D/dalvikvm( 1877): GC_FOR_ALLOC freed 70K, 13% free 3609K/4128K, paused 2ms, tot

    al 3ms

    D/dalvikvm( 1877): GC_CONCURRENT freed <1K, 12% free 4000K/4520K, paused 9ms+0ms

    , total 11ms

    D/dalvikvm( 1877): GC_FOR_ALLOC freed <1K, 12% free 4000K/4520K, paused 2ms, tot

    al 3ms

    I/dalvikvm-heap( 1877): Grow heap (frag case) to 8.641MB for 4510092-byte alloca

    tion

    D/dalvikvm( 1877): GC_CONCURRENT freed <1K, 6% free 8405K/8928K, paused 13ms+0ms

    , total 15ms

    I/dalvikvm( 1877): Could not find method android.webkit.CookieManager.setAcceptT

    hirdPartyCookies, referenced from method org.apache.cordova.engine.SystemCookieM

    anager.

    W/dalvikvm( 1877): VFY: unable to resolve virtual method 219: Landroid/webkit/Co

    okieManager;.setAcceptThirdPartyCookies (Landroid/webkit/WebView;Z)V

    D/dalvikvm( 1877): VFY: replacing opcode 0x6e at 0x0016

    I/dalvikvm( 1877): Could not find method android.webkit.CookieManager.flush, ref

    erenced from method org.apache.cordova.engine.SystemCookieManager.flush

    W/dalvikvm( 1877): VFY: unable to resolve virtual method 214: Landroid/webkit/Co

    okieManager;.flush ()V

    D/dalvikvm( 1877): VFY: replacing opcode 0x6e at 0x0008

    W/dalvikvm( 1877): VFY: unable to find class referenced in signature (Landroid/w

    ebkit/ClientCertRequest;)

    W/dalvikvm( 1877): VFY: unable to find class referenced in signature (Landroid/w

    ebkit/ClientCertRequest;)

    I/dalvikvm( 1877): Could not find method android.webkit.WebViewClient.onReceived

    ClientCertRequest, referenced from method org.apache.cordova.engine.SystemWebVie

    wClient.onReceivedClientCertRequest

    W/dalvikvm( 1877): VFY: unable to resolve virtual method 269: Landroid/webkit/We

    bViewClient;.onReceivedClientCertRequest (Landroid/webkit/WebView;Landroid/webki

    t/ClientCertRequest;)V

    D/dalvikvm( 1877): VFY: replacing opcode 0x6f at 0x001a

    I/dalvikvm( 1877): Could not find method android.webkit.WebChromeClient$FileChoo

    serParams.createIntent, referenced from method org.apache.cordova.engine.SystemW

    ebChromeClient.onShowFileChooser

    W/dalvikvm( 1877): VFY: unable to resolve virtual method 233: Landroid/webkit/We

    bChromeClient$FileChooserParams;.createIntent ()Landroid/content/Intent;

    D/dalvikvm( 1877): VFY: replacing opcode 0x6e at 0x0000

    D/SystemWebViewEngine( 1877): CordovaWebView is running on device made by: unkno

    wn

    D/PluginManager( 1877): init()

    D/dalvikvm( 1877): GC_FOR_ALLOC freed 4883K, 60% free 3648K/8980K, paused 2ms, t

    otal 3ms

    I/dalvikvm-heap( 1877): Grow heap (frag case) to 13.372MB for 9830412-byte alloc

    ation

    E/chromium( 1877): [ERROR:gl_surface_egl.cc(169)] No suitable EGL configs found.

    E/chromium( 1877): [ERROR:gl_surface_egl.cc(702)] GLSurfaceEGL::InitializeOneOff

    failed.

    D/dalvikvm( 1877): GC_CONCURRENT freed 1K, 29% free 13247K/18584K, paused 13ms+0

    ms, total 15ms

    W/chromium( 1877): [WARNING:proxy_service.cc(890)] PAC support disabled because

    there is no system implementation

    I/Choreographer( 1371): Skipped 31 frames! The application may be doing too muc

    h work on its main thread.

    I/Choreographer( 1243): Skipped 36 frames! The application may be doing too muc

    h work on its main thread.

    V/StatusBar( 1877): StatusBar: initialization

    I/dalvikvm( 1877): Could not find method android.content.Context.getExternalMedi

    aDirs, referenced from method org.apache.cordova.file.LocalFilesystem.isPublicDi

    rectory

    W/dalvikvm( 1877): VFY: unable to resolve virtual method 65: Landroid/content/Co

    ntext;.getExternalMediaDirs ()[Ljava/io/File;

    D/dalvikvm( 1877): VFY: replacing opcode 0x6e at 0x000b

    D/FileUtils( 1877): Unrecognized extra filesystem identifier: files-external

    D/FileUtils( 1877): Unrecognized extra filesystem identifier: sdcard

    D/FileUtils( 1877): Unrecognized extra filesystem identifier: cache-external

    D/CordovaWebViewImpl( 1877): >>> loadUrl(file:///android_asset/www/index.html)

    D/CordovaActivity( 1877): Started the activity.

    D/CordovaActivity( 1877): Resumed the activity.

    D/gralloc_goldfish( 1877): Emulator without GPU emulation detected.

    I/ActivityManager( 1243): Displayed com.ionicframework.filebrowserapp139077/.Mai

    nActivity: +1s449ms

    D/AndroidRuntime( 1866): Shutting down VM

    D/dalvikvm( 1866): GC_CONCURRENT freed 96K, 15% free 579K/680K, paused 43ms+1ms,

    total 44ms

    D/CordovaWebViewImpl( 1877): onPageDidNavigate(file:///android_asset/www/index.h

    tml)

    I/Choreographer( 1243): Skipped 59 frames! The application may be doing too muc

    h work on its main thread.

    D/JsMessageQueue( 1877): Set native->JS mode to OnlineEventsBridgeMode

    D/CordovaWebViewImpl( 1877): onPageFinished(file:///android_asset/www/index.html

    )

    V/StatusBar( 1877): Executing action: _ready

    W/CordovaPlugin( 1877): Attempted to send a second callback for ID: StatusBar714

    514405

    W/CordovaPlugin( 1877): Result was: “Invalid action”

    I/App ( 1877): WARNING: Back Button Default Behavior will be overridden. Th

    e backbutton event will be fired!

    V/StatusBar( 1877): Executing action: styleDefault

    W/AssetFilesystem( 1877): Asset manifest not found. Recursive copies and directo

    ry listing will be slow.

    D/dalvikvm( 1358): GC_CONCURRENT freed 450K, 20% free 4068K/5076K, paused 1ms+2m

    s, total 17ms

    D/InputEventConsistencyVerifier( 1877): TouchEvent: ACTION_DOWN but pointers are

    already down. Probably missing ACTION_UP from previous gesture.

    D/InputEventConsistencyVerifier( 1877): in [email protected]

    30add60

    D/InputEventConsistencyVerifier( 1877): 0: sent at 554433689000, MotionEvent {

    action=ACTION_DOWN, id[0]=0, x[0]=481.0, y[0]=444.0, toolType[0]=TOOL_TYPE_FING

    ER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, histor

    ySize=0, eventTime=554433, downTime=554433, deviceId=0, source=0x1002 }

    D/InputEventConsistencyVerifier( 1877): — recent events —

    D/InputEventConsistencyVerifier( 1877): 1: sent at 553045161000, MotionEvent {

    action=ACTION_DOWN, id[0]=0, x[0]=517.0, y[0]=399.0, toolType[0]=TOOL_TYPE_FING

    ER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, histor

    ySize=0, eventTime=553045, downTime=553045, deviceId=0, source=0x1002 }

    D/InputEventConsistencyVerifier( 1877): 2: sent at 487015000000, MotionEvent {

    action=ACTION_CANCEL, id[0]=0, x[0]=0.0, y[0]=0.0, toolType[0]=TOOL_TYPE_UNKNOW

    N, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, history

    Size=0, eventTime=487015, downTime=487015, deviceId=0, source=0x2 }

    • Not sure if this is the reason:

      Maybe there is a possible bug in the Apache Cordova plugin?

      • chungyan5

        hi Indika Ratnayake,

        I got the same log and situation to you that cannot list the folder content, did you solve this problem? if yes, could you please share your solution?

        • chungyan5

          hi,

          just sharing my finding.

          I got it to work now that i need to keep [email protected], not the latest one. I have not yet dug into the reason.

  • matt downing

    Hi nic, I am new in ionic and angular
    a quick question, where I have to put some conditional statement(for broken image) and loop(multiple download)?

  • Stevie Starosciak

    Nic! Do you know if there is an abort function inside the file transfer plugin? I’m currently using the $cordovaFileTransfer plugin with ngCordova, and I have a need where a download needs to be canceled if the user navigates away from the view. I’ve documented the issue in this stackoverflow post: http://stackoverflow.com/questions/34646165/ngcordova-cordovafiletransfer-how-to-abort-a-download-abort-is-undefined

    I feel this would be a common use case, so I wonder if there’s a straightforward way to do this, that I’m missing. Thanks boss 😀

  • Tim

    Hey Nic,
    big big big big big thanks for this solution! Great! 🙂 After three workdays I can download files into my cordova/ionic/angular app! Thank your very much! 🙂
    Couse the user will download big data (map-file/offline-map-file, around 200 MB) – is there a possibility to add a progress bar? Into the HTML-View oder into the ionicLoading box? I hope… but I’ve no idea 🙁

    I can deliver the size of the downloded file via xhr..if it helps?!

    • Tim

      argh i feel so nooby ._.

      • Did you figure it out? I personally would just trigger an $ionicLoading and dismiss it in the callback of the file plugin. Keeping track of actual progress tends to be unreliable which is why I think a generic spinner would be fine.

        Best,

        • Tim

          No, sadly not… i’m programming PHP for years – but learned the
          basics of js and aJS just a few month ago… Hm a normal spinner can
          cause a bad user experience…. depending on the speed of the connection
          a 200 to 400 MB Download can be very long… hm, i will post that to
          stackoverflow… eventuelly someone has an idea 🙂

          • You probably shouldn’t be transferring more than 20mb at a time on a mobile device. 400mb is scary, specially since most people don’t have unlimited data plans.

  • Jack Meyer

    Hi,
    We set a version of this code up inside a loop, and initially it appeared to work (It created all the files with the correct names in the location that we specified) however every file ends up with the same content. For example if we were downloading 5 images (1.png, 2.png, 3.png, 4.png, 5.png) in that order, every image we open is the 5.png picture… Do you have any idea as to why this might be happening?

    • Well it is asynchronous so my assumption is that you’re stepping on yourself with processes.

  • Domenico Carbone

    Hi Nic,

    thanks for the post! I test it and it works fine! I must create an app for business agents of a store with an ecommerce. The database is updated constantly online and images also. Business agents could not have always connectivity on their device, so I think that they can download the database (a json file) and products images and replace old version when they have a connectivity. So, I want to know where files are downloaded both for iOS and for android. Inside the app, for example a folder that I can name store_data?

    • Yes you define the location on where to save things

  • Arnold Tan

    Hi Nic, can i know how to know that file has been downloaded before so i don’t need to download it again

    • You can store information about the file in a database and check the database before trying to download again.

    • Danilo Del Fio

      You can create a factory, with a simple function:

      I use to save path with a check of the device, so, in your controller you can do:

      var isIOS = ionic.Platform.isIOS();
      var isAndroid = ionic.Platform.isAndroid();
      $scope. filePath = {};
      if(isIOS) {
      $scope. filePath = cordova.file.documentsDirectory;
      } else if (isAndroid) {
      $scope. filePath = cordova.file.externalApplicationStorageDirectory;
      }

      and then call your factory function with $scope.filePath like first parameter and the name of the file like second.

      var fileExist= FileDownload.checkFile($scope.filePath,fileName);

      // obviously you can create whatever path starting with $scope.filePath. EX: $scope.filePath+”appName/files”;

      Then the factory:

      var factoriesModule = angular.module(‘simple.services’, []);
      factoriesModule.factory(‘FileDownload’, function(…$cordovaFile) {
      var factory= {};
      ….

      }

      I hope this will answer your question.

  • Jed Nocum

    Good day sir, can I also download a file from the local storage of the device instead fetching the image in the internet like in the tutorial? Sorry for the noob question

  • Jed Nocum

    Good day sir, can I also use this as a saving feature in an app? Like a text input from a user, then save it in the local storage?

    • I’m not sure what you are referring to. The file plugins are for interfacing with the file system. Ideally you would want to save text input to HTML5 local storage or SQLite.

  • Kopinath Nallhaswami

    Hi Nic, I was trying to build a file browser in ios similar to https://www.airpair.com/ionic-framework/posts/ionic-file-browser-app
    i followed ur tutorial it works fine in Android platform but it doesnt return any folders in IOS platform. can u help me with tat it will be useful for all..

    • What do your logs say for iOS? And what version of iOS are you using?

  • Sohitri Sen

    Hi Nic, I am facing an issue for image downloading. Can you please help? http://stackoverflow.com/questions/36687060/image-file-download-issue-in-ionic-for-ios-platform

  • Felipe

    Does this work with a sdcard?

    • It should, but honestly I’ve never tried.

  • hi… i followed your code…
    but anytime i click on the download button the ionicloading icon keeps spinning. please help me out here is my download function.

    // controller.js
    $scope.download = function(){

    $ionicLoading.show({

    });

    document.addEventListener(“deviceready”, function() {

    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fs) {

    }

    );

    }, false);

    }

    //html file
    Download

  • nuruddin

    hi .. how i make folder in project files and download all resource on it ?

  • ravensnowbird

    @nicraboy:disqus Would you be able to make the same tutorial for ionic 2 when you have some free time? I am not able to figure out anything that’s on ionic 2 documentation 🙁

  • krrish Krishna

    Hi, i am following your ionic tutorials and thank you for the wonderful posts, here in this instead of loading can we show % of file download ..

  • Pradeep S

    Hi Nic,

    I have copied you code to my project got Request for filesystem failed.

  • Shubham

    Hello Nic,
    Awesome example but i have one query,can we do same for downloading pdf/word file in the mobile.
    Thanks.

    • You’ll be able to download them but probably not be able to display within the app

      • Shubham

        thanks a ton nic for your response.I am getting file into android folder .
        I wonder if you tell me how to set the path of downloaded file.I want to set into document folder in device storage.Below is my code for target path

        var targetPath = cordova.file.externalRootDirectory + filename;
        This code showing the target below file:///storage/emulated/0/Android/data/io.cordova.myappcac12d/files/ProjectManagement.docx

        I appreciate your response.

        Thanks.

  • Arnaud Hamzaoui

    Hi ! First of all really thank you for your tutorial, after a long day of web searching finally a solution clearly explained.
    But : I’m trying your solution and apparently that’s working but I can’t find the file downloaded on the device.
    I’ve tried on emulators and on real devices. The image appears in the app after being downloaded but I cant find it after on the storage of the device.

    Could you help me ? Maybe I’ve to specify another filepath which is already on the device ?

    • It you’re saving it to the protected device partition, you won’t be able to directly access it unless your device is rooted or jail broken.

      You might want to read up on the device paths in the plugin documentation.

  • adedeji92

    Hello Nick, please can we have a way to delete those files

  • Jose Manuel Mendez

    Thanks man, however i followed the steps and in the end just appears the buttons (that doesn’t work) and {{imgFile}} :/ any idea?

    • What do your logs say?

      • Jose Manuel Mendez

        It’s ok man I already found my mistake haha thanks again

  • Hi Nic,
    Do you have Ionic 2 or 3 version of this? Thanks.