Cordova file-transfer plugin not working in simulator - cordova-plugins

I'm trying to get the example code for the file-transfer plugin working, it's taken straight from the Cordova docs:
function downloadFile2() {
window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
console.log('file system open: ' + fs.name);
// Make sure you add the domain name to the Content-Security-Policy <meta> element.
var url = 'http://cordova.apache.org/static/img/cordova_bot.png';
// Parameters passed to getFile create a new file or return the file if it already exists.
fs.root.getFile('downloaded-image.png', { create: true, exclusive: false }, function (fileEntry) {
download2(fileEntry, url, true);
}, function () { logError('Error creating file'); });
}, function () { logError('Error creating fs'); });
}
function download2(fileEntry, uri, readBinaryData) {
var fileTransfer = new FileTransfer();
var fileURL = fileEntry.toURL();
console.log('Downloading ' + uri + ' to ' + fileURL);
fileTransfer.download(
uri,
fileURL,
function (entry) {
console.log("Successful download...");
console.log("download complete: " + entry.toURL());
if (false && readBinaryData) {
// Read the file...
readBinaryFile(entry);
}
else {
// Or just display it.
displayImageByFileURL(entry);
}
},
function (error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
},
null, // or, pass false
{
//headers: {
// "Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
//}
}
);
}
function displayImageByFileURL(fileEntry) {
var elem = document.getElementById('imageElement');
elem.src = fileEntry.toURL();
}
I'm using the latest versions of the file-transfer and file plugins (1.7.1/6.0.1). I have added the domain to the Content-Security-Policy element as mentioned in the example:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: http://cordova.apache.org https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
When I run it up in the simulator (Android/iOS) from VS2017 the download fails silently. Neither the success or error callbacks are called, and it doesn't appear to generate a network request. The console log is as follows:
file system open: http_localhost_4400:Temporary
Downloading http://cordova.apache.org/static/img/cordova_bot.png to filesystem:http://localhost:4400/temporary/downloaded-image.png
That filesystem URL looked a bit odd to me, so I have tried other variants such as the full file path, using persistent storage instead of temporary, using 'cdvfile://localhost/persistent/downloaded-image.png', all with the same result. I'm at a loss as to how I can debug this further and wondering if I've missed something really obvious, so any advice appreciated...
Edit
I tried running it again today, and a dialog pooped up in Visual Studio with the message:
There is no handler for the following exec call:
FileTransfer.download("http://cordova.apache.org/static/img/cordova_bot.png", "cdvfile://localhost/persistent/downloaded-image.png", true, 1, null)

I did some more experimenting, including running it up in the VS simulator for Android. For some reason it had trouble connecting to cordova.apache.org (I was also unable to access this site in the browser on the emulator), but downloading a file from github worked correctly....

Related

Open local files in ionic iOS

I'm trying to open an already present .pdf file on iOS [I can see the files in iBooks].
I use Ionic and the file-opener2 Cordova plugin - I use the latest versions of Cordova and the plugin.
This is the code that works perfectly on Android:
$scope.openPDF = function() {
alert("OK");
$cordovaFileOpener2.open(
'/storage/emulated/0/Download/pdf/name.pdf', // Any system location, you CAN'T use your appliaction assets folder
'application/pdf'
).then(function() {
console.log('Success');
}, function(err) {
console.log('An error occurred: ' + JSON.stringify(err));
});
};
Yes, I want to be a local file without having to download it, this is a show off app that won't have internet connection where will be running for just one day. So the files have to be local.
I have no idea how to open the file paths like in Android. Running on iOS 9.3.3., iPad Pro. Also, the device is not jail-broken.
Edit:
Well, now I'm trying to move the files from the app's folder to another one, so I can open it from there. Again, all of the code works on Android.
function openPDF(uri) {
var filePath = cordova.file.applicationDirectory + 'www/pdf/fichas/name.pdf';
alert(filePath);
window.resolveLocalFileSystemURL(filePath, function(entry) {
var fileTransfer = new FileTransfer();
var targetFile = cordova.file.externalDataDirectory + entry.name;
fileTransfer.download(
entry.toURL(),
targetFile,
function(entry) {
console.log("download complete: " + entry.toURL());
console.log("targetFile: " + targetFile);
cordova.plugins.fileOpener2.open(
targetFile,
'application/pdf',
{
error : function(error){ alert('open error ' + JSON.stringify(error)) },
success : function(){ }
}
);
},
function(error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
}
);
}, function(error){ alert('error resolveLocalFileSystemURI ' + JSON.stringify(error)) });
};
alert(filePath); * returns: file:///var/containers/Bundle/Application/xxxx-xxxx-xxxx-xxxxxxxxxxxxxxx/NAME.app/www/pdf/name.pdf
I don't know where it fails though. I won't open anything.
edit2:
I get a FileTransfer error indeed. "
Could not create path to save dowloaded file.

PhoneGap download image to a specific folder

I am building PhoneGap based application for iOS platform.
I want to download few image files to a specific directory.
I want to store downloaded images in folder www/my_img/
So that in my app I can further use this image as:
<img src="my_img/downloaded.jpg" width="100px" height="100px">
I am using PhoneGap plugin for downloading images:
var url = 'http://myServer.com/img.jpg';
var filePath = 'www/my_img/';
var fileTransfer = new FileTransfer();
var uri = encodeURI(url);
fileTransfer.download(
uri,
filePath,
function(entry) {
console.log("download complete: " + entry.fullPath);
},
function(error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
},
false,
{
headers: {
}
}
);
But problem is image is not getting saved in specified folder.
How can I save downloaded image in "www/my_img/" folder?
The problem is in the value for filePath. This needs to be a device-absolute-file-path or a filesystem URL.
Have a look at the comptibility notes part of the docs:
There are some predefined folders which you can use. I think the most appropriate for your case (it's r/w, without the need to set any permissions and is persistent) is:
cordova.file.dataDirectory
You could store your downloaded image there and, when done, set the image src.
Translating this to your case:
HTML
<img id="downloadedimage" width="100px" height="100px">
JS
var url = 'http://myServer.com/img.jpg';
var filePath = cordova.file.dataDirectory + '/img.png';
var fileTransfer = new FileTransfer();
var uri = encodeURI(url);
fileTransfer.download(
uri,
filePath,
function(entry) {
console.log("download complete: " + entry.fullPath);
document.getElementById("downloadedimage").src = entry.toURL();
},
function(error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
},
false,
{
headers: {
}
}
);
I think you should before get access to the filesystem. When ok, you can download the image in the folder you create in the dir you got access. If you need, I can give you a snippet.
EDIT:
1) access to the filesystem:
function onDeviceReady() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFSCategory, fail);
}
2) if filesystem's got, get main dir:
function gotFSCategory(fileSystem) {
window.fileSystem = fileSystem;
fileSystem.root.getDirectory(window.appRootDirName, {
create : true,
exclusive : false
}, dirReadyCategory, fail);
}
3) when main dir is ready, save it and go on:
function dirReadyCategory(entry) {
window.appRootDir = entry;
console.log('application dir is ready with window.appRootDir: '+JSON.stringify(window.appRootDir));
// Start my code:
start_my_code();
}
As for the filepath var, I use this one (one for each file):
var filePath = window.appRootDir.toURL() + fileName;

PhoneGap check if file exists

I want to check if file exists, and if it does not, download it. I have tried suggested solutions in this SO question and this blog post
But none of those solution worked for me. Here is my code based on SO question:
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) {
console.log("gotFS");
getFolder(fileSystem, video.folderName, function(folder) {
console.log("Got folder");
var filePath = folder.toURL() + "\/" + "videotest.mp4";
fileSystem.root.getFile(filePath, { create: false }, playVideo(filePath, true), transferFile(video.uri, filePath));
}, function() {
console.log("failed to get folder");
});
},
function() {
console.log("failed to get filesystem");
});
Play video function looks like this:
function playVideo(uri, hasBeenDownloaded) {
console.log("was video dowloaded already", hasBeenDownloaded);
var player = document.getElementById("videoPlayer");
var source = document.createElement("source");
source.src = uri;
source.type = "video/mp4";
player.appendChild(source);
player.load();
}
And here is transferFile function:
function transferFile(uri, filePath) {
var transfer = new FileTransfer();
transfer.download(
uri,
filePath,
function (entry) {
var targetPath = entry.toURL();
console.log("target path je", targetPath);
document.getElementById("result").innerHTML = "File saved to: " + targetPath;
playVideo(targetPath, false);
},
function (error) {
document.getElementById("result").innerHTML = "An error has occurred: Code = " + error.code;
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
}
);
}
What happens is that both playVideo and transferFile are allays called, no matter if file exists or not.
For example if file already exists, firstly only playVideo will be called and in console it will be logged:
was video dowloaded already: true
And after sometime I see that transferFile function was called, and when file is downloaded it will call playVideo and in console i can see:
was video dowloaded already: false
So why is this happening ?
P.S.
With code suggested in blog post problem is completely same, i.e. both functions are called.
Your code is passing the called function as the callback, not the function itself. Let me give an example. Imagine you have function Foo. It asks you to pass 2 callback functions - one for success, one for failure. You could do this:
function good() { alert('good'); };
function bad() { alert('bad'); };
foo(good, bad);
However, this is what you did:
foo(good(), bad());
This is why you have both being called. You need to change:
fileSystem.root.getFile(filePath, { create: false }, playVideo(filePath, true), transferFile(video.uri, filePath));
to
fileSystem.root.getFile(filePath, { create: false }, playVideo, transferFile);
which means you'll need to access the values you need not as arguments but as regular variables.

Phonegap & iOS simulator - cannot save downloaded file

I'm using Phonegap/cordova and writing a Android/iOS app which will download json data from my server and store locally on device for offline usage. On android, this works perfectly. I don't have an iOS device therefore relying on iOS simulator, and it throws me a "could not create target file" type error.
downloadFile:function(path,uri){
var fileTransfer = new FileTransfer();
fileTransfer.download(
encodeURI(path),
app.getStorageLocation()+"files/"+uri,
function(entry) {
console.log("download complete: " + entry.toURL());
app.progressMove();
},
function(error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
},
false);
}
The getStorageLocation function is:
getStorageLocation:function(){
if(device.platform == 'Android'){
return cordova.file.externalApplicationStorageDirectory;
}
else if(device.platform == 'iOS'){
return cordova.file.documentsDirectory;
}else{
throw new Error('Unsupported platform: '+device.platform);
}
}
On iOS simulator, it does return the Documents directory, but the above fails to write to it. Would this just be a Simulator bug or have I done something wrong?
thanks!
I have created one file named dummy.html under the documents directory. Below is the working code snippet for downloading file. You can log path and see where its pointing. Use safari develop tool iOS simulator for inspecting. I have added file & filetransfer plugin.
function downloadFile() {
window.requestFileSystem(
LocalFileSystem.PERSISTENT, 0,
function onFileSystemSuccess(fileSystem) {
fileSystem.root.getFile(
"dummy.html", {
create: true,
exclusive: false
},
function gotFileEntry(fileEntry) {
console.log(fileEntry);
var sPath = fileEntry.nativeURL.replace("dummy.html", "");
console.log(sPath);
var fileTransfer = new FileTransfer();
fileEntry.remove();
fileTransfer.download(
"http://developer.android.com/assets/images/home/ics-android.png",
sPath + "dummy.png",
function(theFile) {
console.log("download complete: " + theFile.toURI());
showLink(theFile.toURI());
},
function(error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code: " + error.code);
}
);
},
fail);
},
fail);
}
Check screenshot-
excellent! got it working.
Additionally found that not all files were problematic. Apple doesn't like custom file types nor file names with "%20" in them. Fixing all the above has worked!

Set folder metadata doesn't work on Phonegap 3.3.0 / iOS

I'm trying to use the method setMetadata, using the File plugin, but it seems does not work.
No Success or Fail callback is executed. When I use console.log(entry.setMetadata), it prints the correct method. I use the File plugin to access, create and delete files and folders without problems. Only the setMetadata doesn't work.
Example:
localFileSystem = LocalFileSystem.PERSISTENT;
subFolder = "Backups";
metadataKey = "com.apple.MobileBackup";
metadataValue = 1;
window.requestFileSystem(localFileSystem, 0, function(fileSystem) {
fileSystem.root.getDirectory(subFolder, {create: true, exclusive: false}, function(parent) {
var data = {};
data[metadataKey] = metadataValue;
console.log(data); // OK
console.log(parent); // OK
parent.setMetadata(function() {
console.log("success setting metadata"); // Nothing
}, function() {
console.log("error setting metadata"); // Nothing
}, data);
}, function() {
console.log("error getting dir"); // Nothing, directory is OK
});
}, function(error) {
console.log(error.code); // No error here
});
It was a bug on the File plugin. I checked with the developers on Github:
https://github.com/apache/cordova-plugin-file/pull/39
Just waiting for changes on the Phonegap site.

Resources