Copy file to ionic app directory

Hi all, I know this is not an Ionic query at all really, but the help I’ve had from here has been great, so I am trying my luck.

I would like to be able to copy a file from the file system, using the operating system default file selector, into the storage folder of an app (well, a sub directory “Documents”).

I’ve installed the following plugins and am testing with Android

cordova plugin add GitHub - don/cordova-filechooser: Cordova Plugin that supplies a File Chooser
cordova plugin add org.apache.cordova.file

When I run the supplied code (with a button in the view with the code ng-click=“copyImage”) I get the following console log that indicates that the file has actually been copied

download complete: data/data/com.ionicframework.localstorage2811988/Documents2/filename

However, when using a file browser, I don’t seem to be able to find said file!

Can anyone give me any tips? :smile:

As always, thank you. The code follows:

	// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
var exampleApp = angular.module('starter', ['ionic'])

.run(function($ionicPlatform,$rootScope) {
  $ionicPlatform.ready(function() {
	// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
	// for form inputs)
	if(window.cordova && window.cordova.plugins.Keyboard) {
	  cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
	}
	if(window.StatusBar) {
	  StatusBar.styleDefault();
	}
	
  });
});

exampleApp.controller('MainCtrl',function($scope){

  document.addEventListener("deviceready", onDeviceReady, false);

	function onDeviceReady() {
		console.log("device is ready");
		window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
		window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
	}

	function fail() {
		console.log("failed to get filesystem");
	}

	function gotFS(fileSystem) {
		console.log("got filesystem");
		var entry=fileSystem.root; 
		console.log(cordova.file.applicationStorageDirectory+"Documents2");
		entry.getDirectory(cordova.file.applicationStorageDirectory+"Documents2", {create: true, exclusive: false}, function onGetDirectorySuccess(){ console.log("Created directory") }, function(e){ console.log("error"); console.log(e)})

	}

	function downloadImage(url, fileName){
		var ft = new FileTransfer();
		ft.download(
			url,
			cordova.file.applicationStorageDirectory+"Documents2/" + fileName,
			function(entry) {
				console.log(entry);
				console.log("download complete: " + entry.fullPath);

			},
			function(error) {
				console.log("error");
				console.log(error);
				console.log("download error" + error.code);
			}
		);
	}

	$scope.copyImage = function(){
	  fileChooser.open( 
		function fcSuccess(URI){
		  downloadImage(URI,"filename");
		},
		function fcError(e){
		  console.log(e);
		}
	  )
	};

});

If the code above is all rubbish and you can point me in the direction of a guide/example that does what I require, I am very happy to go with that too!

Is your device rooted? If it is not rooted you cannot access application storage directory. If its android emulator you can access files.

Did you check your sdcard for the file? File system request might give you the path of sdcard root folder “file:///storage/0/”. So when you create your folder based on this root, it will be on the sdcard.

Your directory should be “file:///data/data/com.ionicframework.localstorage2811988/Documents2/”. But you might be getting “file:///storage/0/data/data/com.ionicframework.localstorage2811988/Documents2/”

Try checking fileSystem.root.toUrl() to see actual place your file goes.

Thanks Esery1,

nope not rooted.

I’ve changed the directory to cordova.file.dataDirectory which points to

file:///data/data/com.ionicframework.localstorage2811988/files/

The controller source is now

exampleApp.controller(‘MainCtrl3’, function($scope){

  $scope.copyImage = function() {
    //navigator.camera.getPicture(onPhotoURISuccess, fail, { quality: 25, destinationType: Camera.DestinationType.FILE_URI });
    fileChooser.open(
      onFCSuccess,
      fail
    );
  }

  function onFCSuccess(fileURI) {
    console.log("fileURI");
    console.log(fileURI);
    createFileEntry(fileURI);
  }

  function createFileEntry(fileURI) {
    window.resolveLocalFileSystemURL(fileURI, copyFile, fail);    
  }

  function copyFile(fileEntry) {

    console.log("copyFile fileEntry");
    console.log(fileEntry);
    console.log("cordova.file.dataDirectory");
    console.log(cordova.file.dataDirectory);

    window.resolveLocalFileSystemURL(
      cordova.file.dataDirectory, 
      function(fileSystem2) {

        fileEntry.copyTo(
          fileSystem2, 
          "file3.jpg", 
          onCopySuccess, 
          fail
        );
        
      }, 
      fail
    ); 
  }

  function onCopySuccess(entry) {
    console.log(entry);
  }

  function fail(error) {
    console.log(error.code);
  }

});

and onCopySuccess spits out the following. Seems like an odd full path to me? (or is that the full parth in relation to the file system) Regardless though, while I am not getting any errors, it’s not copying?

FileEntry {isFile: true, isDirectory: false, name: "file3.jpg", fullPath: "/file3.jpg", filesystem: FileSystem…}
filesystem: FileSystem
fullPath: "/file3.jpg"
isDirectory: false
isFile: true
name: "file3.jpg"
nativeURL: "file:///data/data/com.ionicframework.localstorage2811988/files/file3.jpg"
__proto__: utils.extend.F

FileEntry fullPath might be relative to cordova.file.dataDirectory. nativeUrl seems to be correct.
I think your file is copied succesfully.

Following link shows how to access to an android device file system with adb shell.

1 Like

Haha, well, I guess it was working all along and I’m just a moron! I can now see that when I adb into my phone as the app, all of my previous “failed” attempts are there and it is in fact working as expected… DOH!

Thanks Esery, I’ve no idea how I would’ve worked that one out.

Well, this happened to me also :slight_smile: Happy to help.

Me again!

OK, I’m now able to select a file and store it locally a data directory. However, it seems that the original filename is lost… this makes opening, let’s say, a pdf using the File Opener plugin impossible, unless, when I am saving the file I hard code FILE + “.pdf”

As an example, the native URL of a file I’ve copied is…

file:///storage/emulated/0/Android/data/it.ct14.parker/4998

it seems like at no point I am given access to the actual file name? I assume this is something really dumb on my part, but I am stumped! :S

I think you have to specify full path including extension while using fileEntry.copyTo and FileTransfer.Download.

Hi Esery,

how do I get the full path including extension though?

I’m able to copy the file, but I’m not able to copy the file and use the actual file name shown in the file browser.

For example:

file:///storage/emulated/0/Android/data/it.ct14.parker/4998

was actually a copy of the file (in my Downloads directory)

A-Z_Business_Conduct.pdf

I want to copy said file to the location

file:///storage/emulated/0/Android/data/it.ct14.parker/A-Z_Business_Conduct.pdf

But for the life of me, I can’t get the actual file name it seems :S

Try with cordova.file.externalDataDirectory instead of cordova.file.applicationStorageDirectory . i had the same problem.