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;
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.
My app downloads images from an external resource to the data directory using FileTrasnfer. Now, in one of the pages of my app I'm supposed to display those images.
The paths I used for the images is the exact path they were downloaded to, then I don't understand why the images are not displayed, seems like there is no access to the file
How can I access files in the file.datadirectory?
my code
getfileimage() {
const fileTransfer: FileTransferObject = this.transfer.create();
let options ={
headers:{
'token': this.token,
'sid': this.sid,
'user': this.user,
'type': "image",
'file': this.FileName
}
}
fileTransfer.download(this.apiUrl, this.file.dataDirectory + 'photo.jpg', true, options)
.then(result => {
console.log("getfileimage 2 :- " + JSON.stringify((result)));
console.log("Response data ->>>>>>> :- " + JSON.stringify(result.nativeURL));
// this.imageDis = normalizeURL(JSON.stringify(result.nativeURL));
this.imageDis = JSON.stringify(result.nativeURL);
//console.log("getfileimage :- " +this.imageDis);
}, (err) => {
console.log("Error is: " + JSON.stringify(err));
});
output :-----
getfileimage :- "file:///var/mobile/Containers/Data/Application/E806FDE7-1AF2-4DA2-BC07-E5FEC2E422ED/Library/NoCloud/photo.jpg"
2018-02-26 17:28:11.911819+0530 MyApp[607:174952] THREAD WARNING: ['File'] took '10.540039' ms. Plugin should use a background thread.
2018-02-26 17:28:11.936391+0530 MyApp[607:174952] WARNING: sanitizing unsafe URL value "file:///var/mobile/Containers/Data/Application/E806FDE7-1AF2-4DA2-BC07-E5FEC2E422ED/Library/NoCloud/photo.jpg" (see http://g.co/ng/security#xss)
2018-02-26 17:28:11.970340+0530 MyApp[607:174952] localFile :- cdvfile://localhost/library-nosync/photo.jpg
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 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.
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!