Following this yet unanswered question I ran some tests to see where the problem is - in my side or in the server side.
So taking into account it might be a image codec problem, I have tried to upload a text/plain file to my server using post method.
First, I made sure the file exists by calling readAsText() method:
function onDeviceReady() {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
}
function gotFS(fileSystem) {
fileSystem.root.getFile("textfile.txt", null, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
fileEntry.file(gotFile, fail);
}
function gotFile(file){
readDataUrl(file);
readAsText(file);
}
function readDataUrl(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
alert("Read as data URL");
alert(evt.target.result);
};
reader.readAsDataURL(file);
}
function readAsText(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
alert("Read as text");
alert(evt.target.result);
};
reader.readAsText(file);
}
function fail(evt) {
alert(evt.target.error.code);
}
After I get an alert with text file URL and text file content, I know this is my file. Now I'm uploading it:
function gotFile(file){
// alert('gotFile')
// readDataUrl(file);
// readAsText(file);
alert(file.fullPath)
uploadText(file.fullPath)
}
function uploadText(fileURI) {
alert('uploading file...')
function win(r) {
alert("Code = " + r.responseCode);
alert("Response = " + r.response);
alert("Sent = " + r.bytesSent);
}
function fail(error) {
alert("An error has occurred: Code = " + error.code);
alert("http_status = " + error.http_status);
alert("upload error source " + error.source);
alert("upload error target " + error.target);
}
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);
options.mimeType = "text/plain";
var ft = new FileTransfer();
ft.upload(fileURI, encodeURI("https://mysecureurl.com/?filename="+options.fileName), win, fail, options);
}
I get fileTransfer error code 1 (file not found) and http status code 411 (malformed request).
I have all the permission including fileTransfer in my android project and also <access origin="*"/>. My server administrator says he gets the request but something is broken in the middle when I am sending file from phonegap (unlike normal browser requests) and he couldn't figure out what is it.
I am really stuck here. Is there any PhoneGap limitation I am not aware of? Or is there anyway to capture phone's http body request so I could debug it?
The problem is with content-type. Phonegap sets Content-Type: multipart/form-data;boundary=+++++ omitting the whitespace in between. Some servers can be picky with this. I solved the issue by rewriting this header and adding a whitespace as follows: Content-Type: multipart/form-data; boundary=+++++. Although this sounds like a hack, and solves the issue for me, this change needs to be incorporated into phonegap Android library in future releases.
It just happend on Android platform and fine on iOS, so try to set options.chunkedMode=false just on Android (the chunkedMode options default is true). see https://github.com/apache/cordova-plugin-file-transfer/pull/141#issuecomment-291776345
Related
I'm building an app with PhoneGap Build, only targeting Android. One of the features is to download a file from a web server to the device.
This code works perfectly on Android 4.x, but doesn't work on Android 5.x and above:
var URL = 'https://example.com/path/to/file.pdf?auth_token=123xxxx';
var Folder_Name = 'Download';
var File_Name = URL.split('/');
File_Name = File_Name[File_Name.length - 1].split('?');
File_Name = File_Name[0];
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fileSystemSuccess, fileSystemFail);
function fileSystemSuccess(fileSystem) {
var download_link = encodeURI(URL);
var directoryEntry = fileSystem.root; // to get root path of directory
directoryEntry.getDirectory(Folder_Name, {
create: true,
exclusive: false
}, onDirectorySuccess, onDirectoryFail); // creating folder in sdcard
var rootdir = fileSystem.root;
var fp = rootdir.toURL(); // Returns Fullpath of local directory
fp = fp + "/" + Folder_Name + "/" + File_Name; // fullpath and name of the file which we want to give
console.log("Path to local file: " + fp);
// download function call
filetransfer(download_link, fp);
}
function onDirectorySuccess(parent) {
console.log('directory created successfully');
// Directory created successfuly
}
function onDirectoryFail(error) {
//Error while creating directory
console.log("Unable to create new directory: " + error.code);
}
function fileSystemFail(evt) {
//Unable to access file system
console.log(evt.target.error.code);
}
function filetransfer(download_link, fp) {
var fileTransfer = new FileTransfer();
// File download function with URL and local path
fileTransfer.download(download_link, fp,
function(entry) {
alert('The file was successfully downloaded, you can access it in /' + Folder_Name + '/' + File_Name + '.');
console.log("download complete: " + entry.fullPath);
},
function(error) {
//Download abort errors or download failed errors
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("download error code" + error.code);
}
);
}
Don't get anything in the console, no error and none of the log lines, meaning that none of the callbacks gets triggered.
Did anybody else have this mysterious issue?
Thanks
try to install these versions.
phonegap plugin remove cordova-plugin-file
phonegap plugin remove cordova-plugin-file-transfer
phonegap plugin add cordova-plugin-file#4.3.3
phonegap plugin add cordova-plugin-file-transfer#1.5.1
I am use these versions and i havent problems in Anrdoid 5, 6, 7. Try it.
I have been using phonegap and am trying to download wallpaper jpgs to the device camera roll. I have been testing this on the mobile phonegap app connecting to phonegap server. The code I am using goes as follows:
function DownloadFile(URL, Folder_Name, File_Name) {
if (URL == null && Folder_Name == null && File_Name == null) {
return;
}
else {
download(URL, Folder_Name, File_Name); //If available download function
}
}
function download(URL, Folder_Name, File_Name) {
//step to request a file system
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fileSystemSuccess, fileSystemFail);
function fileSystemSuccess(fileSystem) {
var download_link = encodeURI(URL);
ext = download_link.substr(download_link.lastIndexOf('.') + 1); //Get extension of URL
var directoryEntry = fileSystem.root; // to get root path of directory
directoryEntry.getDirectory(Folder_Name, { create: true, exclusive: false }, onDirectorySuccess, onDirectoryFail); // creating folder in sdcard
var rootdir = fileSystem.root;
var fp = rootdir.toURL(); // Returns Fulpath of local directory
fp = fp + Folder_Name +"/"+ File_Name + ".jpg"; // fullpath and name of the file which we want to give
filetransfer(download_link, fp);
}
function onDirectorySuccess(parent) {
// Directory created successfuly
}
function onDirectoryFail(error) {
//Error while creating directory
alert("Unable to create new directory: " + error.code);
}
function fileSystemFail(evt) {
//Unable to access file system
alert(evt.target.error.code);
}
}
function filetransfer(download_link, fp) {
var fileTransfer = new FileTransfer();
// File download function with URL and local path
fileTransfer.download(download_link, fp,
function (entry) {
console.log("cdvfile://localhost/persistent/" + fp);
alert("download complete: " + entry.fullPath.slice(1));
},
function (error) {
//Download abort errors or download failed errors
alert("download error source " + error.source);
alert("download error target " + error.target);
//alert("upload error code" + error.code);
}
);
}
What is interesting is that when I click my button that fires these methods I receive an alert saying download complete: file_name. However, there never appears an image in my camera roll. Is this an iOS issue? I've tried looking at this natively as opposed to simulating it with phonegap serve and it makes no difference.
I've also tried a file_path like so "cdvfile://localhost/persistent/"+Folder_name+"/"+ File_name+"."+ext;
with no different results.
In a difference post http://community.phonegap.com/nitobi/topics/file_download_not_working_properly_on_ios the answer for iOS was to use
<access origin="*" />
I made sure to use that in my config.xml file.
Does anyone have an idea as to what I am missing? This code has worked for others and oddly it states it completes correctly.
I'm using Cordova to make android and iOS app, now I would like to check if file already exist in the dirctory.
First I download file from server and save it locally using the code below
$scope.downloadFile = function(){
alert(cordova.file.dataDirectory)
var fileTransfer = new FileTransfer();
var uri = encodeURI("http://example.com/files/th/001.mp3");
var downloadPath = cordova.file.dataDirectory+'001.mp3'; // ANDROID
fileTransfer.download(
uri,
downloadPath,
function(entry) {
$scope.savepath = entry.toInternalURL();
alert("download complete: " + entry.toURL());
alert('saved at : '+entry.toInternalURL());
},
function(error) {
alert("download error source " + error.source);
alert("download error target " + error.target);
alert("upload error code" + error.code);
},
false,
{
headers: {
"Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
}
}
);
}//End DownloadFile
and I would like to check if the file already exist using checkIfFileExists(path) method
function checkIfFileExists(path){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
//alert('result: '+JSON.stringify(fileSystem.root))
fileSystem.root.getFile(path, { create: false }, fileExists, fileDoesNotExist);
}, getFSFail); //of requestFileSystem
}
function fileExists(fileEntry){
alert("File " + fileEntry.fullPath + " exists!");
}
function fileDoesNotExist(){
alert("file does not exist");
}
function getFSFail(evt) {
console.log(evt.target.error.code);
}
I checked on my phone, the file is already saved to Android/data/com.myname.myappname/file/001.mp3
but the problem is the code always show file does not exist whenever I use the path like
cordova.file.dataDirectory+'001.mp3';
or cdvfile://localhost/persistent/files/001.mp3
or 'cdvfile://localhost/files/001.mp3'
so I would like to ask that the real path that I need to use to check if the file exist or not.
Please provide me any suggestion.
Regards.
Do you need to use or CheckFileExists? You could try using Phonegap's FileReader method?
var reader = new FileReader();
var fileSource = cordova.file.dataDirectory+'001.mp3'
reader.onloadend = function(evt) {
if(evt.target.result == null) {
// Null? You still have a problem: file doesn't exist.
} else {
// Otherwise the file exists.
}
};
//Check if the file exists
reader.readAsDataURL(fileSource);
I am using phonegap 3.0.0
And in the process of attempting to upload a file to the server I am getting a couple things that are unexpected. First thing, a script error:
Error: SyntaxError: Unexpected token ':' line 624 of phonegap.js
(which I think is a lot older version of the js to begin with, as I could only find one on github)
Next thing I am getting which I don't see why/how this would prompt when I have never seen it on other apps.. is a little alert dialog:
When I click OK on the dialog thats when it attempts to carry out the rest of the script, and gives me the above error.
and the script I am using to upload is based almost to the letter the same as the one found on the phonegap site.. http://docs.phonegap.com/en/3.0.0/cordova_file_file.md.html#File
$('#select_photo').on('click', function()
{
$('#choice_of_file').click();
});
$('#upload_photo').on('click', function()
{
if(fmr.nullCheck($('#choice_of_file').val()) == true)
{
alert('Please Choose a Photo');
}
else
{
uploadPhoto($('#choice_of_file').val());
}
});
// Wait for device API libraries to load
//
(function(){document.addEventListener("deviceready", onDeviceReady, false);})();
// device APIs are available
//
function onDeviceReady() {
// Retrieve image file location from specified source
navigator.camera.getPicture(
uploadPhoto,
function(message) { alert('get picture failed'); },
{
quality : 50,
destinationType : navigator.camera.DestinationType.FILE_URI,
sourceType : navigator.camera.PictureSourceType.PHOTOLIBRARY
}
);
}
function uploadPhoto(imageURI) {
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";
var params = {};
params.value1 = "test";
params.value2 = "param";
options.params = params;
var ft = new FileTransfer();
ft.upload(imageURI, encodeURI(domainURL+'upload/wizard/'+MembId), win, fail, options);
}
function win(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
}
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);
}
the HTML for the form its reading..
<div style="position:absolute;top:-2000px;left:-2000px;background-color:#FFF;z-index:0" id="hide_file_input">
<form enctype="multipart/form-data" id="upload_profile_image" action="#none" method="post">
<input type="file" id="choice_of_file" name="choice_of_file">
</form>
</div>
Filekey should be the name attribute of file field
options.fileKey="choice_of_file";
Also it will be better if you can call deviceready before all functions are executed and put navigator.camera.getPicture in the onclick event of file field
I've already managed to save a web page (x/html) successfully, but I'd also like to save the images and mp4 videos that are contained in it, for further visualization in offline mode.
I've got access to the iOS filesystem, so I save the html by obtaining the code through an AJAX request, and later saving it to a file.
I don't really know how to do the same with video and images. I have a server to which I can send queries from my app, so it shows exclusively the content I need to download, with the optimal headers in case its necessary. I just don't know how to "download" it from the client side (Javascript).
Thanks in advance for any help.
You can use a FileTransfer object to download a remote image to a local file.
This is the latest official sample snippet:
// !! Assumes filePath is a valid path on the device
var fileTransfer = new FileTransfer();
var uri = encodeURI("http://some.server.com/download.php");
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: {
"Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
}
}
);
You can only do it natively I'm afraid.
I'm doing it through a FileDownload PhoneGap Plugin that I wrote, using NSURLConnection. I pass in the url to download to the plugin through Javascript, and a target location (and it even gives me download progress).
Have not tested it yet, but the documentation at PhoneGap looks quite promising http://docs.phonegap.com/en/1.0.0/phonegap_file_file.md.html
I have used this snippet on my ios app project:
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, success, fail);
var target_directory="";
function fail() {
//alert("failed to get filesystem");
}
function downloadImage(url, filename){
alert("download just started.");
try{
var ft = new FileTransfer();
ft.download(
url,
target_directory + filename,
function(entry) {
//alert("download complete!:" + entry.nativeURL ); //path of the downloaded file
},
function(error) {
//alert("download error" + error.code);
//alert("download error" + JSON.stringify(error));
}
);
}
catch (e){
//alert(JSON.stringify(e));
}
}
function success(fileSystem) {
target_directory = fileSystem.root.nativeURL; //root path
downloadImage(encodeURI("http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg"), "cat.jpg"); // I just used a sample url and filename
}