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!
Related
After searching, testing, coding for over 25h now I hope someone can help me with my problem.
I'm using Cordova (v11) with the File-Plugin and I want to store a file (blob) in the "On my iPhone" directory (on android everything is working fine).
I can save it in the app directory where I can also show it in the inappbrowser but I find no way to store it anywhere else - I want to store it in the "on my iPhone" folder..
Here is the code
saveBlobToSystem(filename, blob) {
filename = 'test.pdf'
let showAlert = true
let folderpath = null
if (this.$q.platform.is.android) folderpath = "file:///storage/emulated/0/download/"; // android --> cordova.file.externalRootDirectory + 'download/'
if (this.$q.platform.is.ios) folderpath = cordova.file.dataDirectory + '' // ios
// folderpath = "cdvfile://localhost/persistent/" + filename;
// folderpath = "cdvfile://localhost/temp/"
const onError = function(msg) {
console.log("Error saving File to System: " + JSON.stringify(msg));
if (showAlert) alert("Error saving File to System: " + JSON.stringify(msg));
};
window.resolveLocalFileSystemURL(folderpath, function(fileSystem) {
console.log("Access to the directory granted succesfully");
if (showAlert) alert("Access to the directory granted succesfully" + folderpath);
fileSystem.getFile(filename, {
create: true,
exclusive: false
}, function(file) {
console.log("File created succesfully.");
if (showAlert) alert("File created succesfully." + JSON.stringify(file));
file.createWriter(function(fileWriter) {
console.log("Writing content to file");
if (showAlert) alert("Writing content to file" + JSON.stringify(fileWriter));
alert('filename' + file.nativeURL)
fileWriter.write(blob);
alert('Datei was downloaded')
console.log("Successfully write file to system");
window.cordova.InAppBrowser.open(file, '_blank', 'location=yes');
}, onError);
}, onError);
}, onError);}
If tried all the tricks with the plist and UIFileSharingEnabled but this doesn't help either.
The strange thing is, that all alert/debug messages looking fine but the one where the data should be written. Because there it says that file is written to a CDV-Path.
wrong file location??
The next debug message "filename" again shows the correct path
correct file location
So I hope anyone has solved that problem already.
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....
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.
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;
first, sorry if my english is bad.
Then, here is my issue:
I try to make an app for iOS with PhoneGap 2.8.1 . Evrything is going well on Android, now I just want to move my code on Xcode to compile on iPad or iPhone.
The probleme I have is with FileTransfer, when I upload an image. The transfer itself has no problem, as it finishes with a response code 200, so it's a success.
Then, my serve is supposed to return back an XML file, handled by the javascript code. The server works fine, because I have absolutly no problem with Android devices.
So, I made a lot of tests, and it appears that the app has a problem with the success callback or the FileTransfer.upload(). When I just put a simple console.log('success') in this callback function, it's fine. But when I try to use the FileUploadResult object, nothing happens.
And the weirdest thing is, that when I press the main button of the iPad or iPhone, in order to close my app, I see all my logs displayed in the debug window, such as console.log("Code = " + r.responseCode);, like in the PhoneGap example. And here, I can finally see that I actually receive the server response, but it's like something blocks it until I close the app.
Here is that part of the code :
function onPhotoDataSuccess(imageURI) {
console.log("---> Image: "+imageURI);
// File Transfer
var options = new FileUploadOptions();
options.fileKey="file";
options.chunkedMode = false;
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";
var ft = new FileTransfer();
ft.upload(imageURI, encodeURI(window.localStorage.getItem("wsURL")), win, fail, options);
// Transfer succeeded
function win(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
// Handle the XML response
}
else {
alert("No response. Please retry");
}
}
// Transfer failed
function fail(error) {
alert("An error has occurred: Code = " + error.code);
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
}
}
Thanks for your help