Titanium HTTPCLIENT can't upload file - javascript

I try to use Brower can upload a file, but if I use Titanium upload, it doesn't work,
the brower code is
Brower upload file:
<form action="upload.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
Upload.php file:
$tmp_file=$_FILES['file']['tmp_name'];
$target_file=basename($_FILES['file']['name']);
move_uploaded_file($tmp_file, "files/".$target_file);
my titanium code is:
var webaddress = 'http://' + address.value + ':' + port1.value + '/scanbatch/index.php';
xhr.open('POST',webaddress);
xhr.send({files : Titanium.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory,'scanbatch.txt')});
it can work but the webservice didn't received anything, just received a header.
and by the way , I can send out the short xml through the httpclient ,but if the xml be longer sometime it can't send out, more longer more fail,I mean not always, if the xml longer than 512KB, It always fail.
my code is
var webaddress = 'http://' + address.value + ':' + port1.value + '/liveho/scanbatch';
xhr.open('POST',webaddress);
xhr.send(xmlscript);
my onload function is
onload : function(e) {
alert(this.responseText);
},
please help me thank you

I will give you some advice, to narrow down the problem (Titanium side).
Have you tested if the path to the file is correct?
var file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory +
Ti.Filesystem.getSeparator() + 'scanbatch.txt');
if(file.size)
xhr.send({files : file});
else
Ti.API.info("File " + file.nativePath + " doesn't exist or is empty");
If it isn't the correct path, try to find it in the resourcesDirectory:
var file = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory +
Ti.Filesystem.getSeparator() + 'scanbatch.txt');
Your problem with disconnections might be diminish setting the timeout property. A onerror function could also help you find the problem. The onsendstream property will let you know the progression of the upload.
Ti.Network.createHTTPClient({
...
onload : function(e) {
alert(this.responseText);
},
onerror : function(e) {
Ti.API.debug(e.error);
alert(e.error);
},
onsendstream : function(e) {
var progress = parseFloat(e.progress)*100;
Ti.API.info("Upload progress:" + progress + "%");
//e.progress will contain a value from 0.0-1.0 with the progress of the upload
alert("Upload progress:" + progress + "%");
},
timeout : 5000 // in milliseconds
...
});

Related

How to write response from an http Post request for downloading a file to an iframe element using JS/jQuery?

I'm working on an old piece of code in a software where there's a generic JavaScript (w/ some jQuery) utility function that calls an ASHX web-handler to download any type of file like excel, word, zip, csv, etc. (definition mentioned below). It dynamically creates an iframe & form element with the iframe target, submits the form, and removes the form element.
// existing function
downloadFile: function(url, method, formData) {
// method = by default 'POST' and can be 'GET', 'POST', ...
encUrl = encodeUrl(url);
downloadDiv = $('<div id="download-file" style="display: none;"></div>');
iframeId = getNewId();
src = isPost ? '' : 'src="' + encUrl + '"';
downloadDiv.html('<iframe name="' + iframeId + '" id="' + iframeId + '" ' + src + '></iframe>');
if(isPost) {
form = $('<form target="' + iframeId + '" method="post" action="' + encUrl + '"></form>').appendTo(document.body);
if (formData) {
for (p in formData) {
if (formData.hasOwnProperty(p)) {
$('<input type="hidden" />').attr("name", p).val(formData[p]).appendTo(form);
}
}
}
form.submit().remove();
}
}
At few places in the codebase from where this function is called, I have to delete the file after the user downloads it, so I need a callback to request the server. For this, I have converted this function to use an XHR. I seldom work with JS so this is the best I've been able to do so far. With the code below, the server writes the file in the response but I am not able to write it in the iframe so that the download file popup opens up in the application and the user downloads the file. Basically, I'm trying to imitate the form's target="iframeId" thing in JS.
// modified function
downloadFile: function(url, method, formData, downloadAsync, asyncSuccessCallback, asyncFailureCallback) {
// same as before, just changed the form submit part
if (submitAsync) {
downloadXhr = new XMLHttpRequest();
// is encoded URL required here or the normal one will do?
downloadXhr.open('POST', url);
downloadXhr.onloadend = () => {
var xhr = downloadXhr,
iframeTarget = downloadDiv.children().first().get(0);
form.remove();
iframeTarget.contentDocument.open();
iframeTarget.contentDocument.write(xhr.response);
iframeTarget.contentDocument.close();
}
if (asyncSuccessCallback) {
downloadXhr.onload = asyncSuccessCallback;
}
if (asyncFailureCallback) {
downloadXhr.onerror = asyncFailureCallback;
}
// needed? downloadXhr.responseType = 'blob';
downloadXhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
downloadXhr.send(new FormData(form.get(0)));
}
else {
form.submit().remove();
}
}
How can I write the response to the iframe so that the download file window opens in the browser?
Is this approach correct or something better can be done? Perhaps, AJAX could also be used here instead.
Please help, thanks.

XMLHttpRequest fails reading XML InfoPath form due to mso-application line

I'm trying to create an ASPX page on my SharePoint site to read existing InfoPath forms. Testing locally with JavaScript and XMLHttpRequest worked fine but when the page is uploaded to SharePoint something very odd happens if the XML file has a specific line of data in it. When testing with simple XML files this line causes a problem:
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.4"?>
When present in the XML file I'm trying to read, something odd happens. Instead of getting the contents of the file I get what appears to be an HTML page from SharePoint. The page doesn't display anything and has references to InfoPath and SharePoint libraries. I have no idea where the HTML is coming from. Removing that single line from the XML file causes everything to work as expected. Running outside of SharePoint appears to work as well. I will include a sample XML file and code I used to test.
Update : If the input file extension is TXT and not XML then the problem goes away. I assume this means that SharePoint is running code when XML files are read and injecting itself into my get request.
<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.4"?>
<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2017-05-05T14:19:13">
<my:User_Name>Joe</my:User_Name>
<my:Email_Address>joe.smith#abc.com</my:Email_Address>
</my:myFields>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="lib/jquery/jquery-3.4.1.min.js"></script>
<title></title>
<script>
var oReq = new XMLHttpRequest();
oReq.addEventListener("progress", updateProgress);
oReq.addEventListener("error", transferFailed);
oReq.addEventListener("abort", transferCanceled);
oReq.addEventListener("loadend", transferComplete);
function Test_Req_xml() {
console.log("starting test_req_xml function");
let filename = document.getElementById('inFileName').value;
console.log("file name " + filename);
oReq.addEventListener("load", transferComplete_xml);
oReq.open("GET", filename);
oReq.responseType = "document";
oReq.send();
}
var transferComplete_xml = function (response) {
console.log({ 'transferComplete xml response:': response });
console.log({ 'oReq.responseXML': oReq.responseXML });
console.log({ 'oReq.responseType': oReq.responseType });
console.log({ 'oReq.responseURL': oReq.responseURL });
console.log({ 'oReq': oReq });
parseFile(oReq.responseXML.documentElement.outerHTML);
};
// progress on transfers from the server to the client (downloads)
function updateProgress(oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = oEvent.loaded / oEvent.total * 100;
console.log("percent " + percentComplete);
} else {
// Unable to compute progress information since the total size is unknown
console.log("loaded is " + oEvent.loaded);
}
}
function transferComplete(evt) {
console.log("The transfer is complete.");
}
function transferFailed(evt) {
console.log("An error occurred while transferring the file.");
}
function transferCanceled(evt) {
console.log("The transfer has been canceled by the user.");
}
//this will parse XML file and output it to website
var parseFile = function (text) {
var xmlDoc = $.parseXML(text),
$xml = $(xmlDoc),
$email = $xml.find("Email_Address"),
$naming = $xml.find("User_Name");
console.log({ 'xmldoc ': xmlDoc });
var currentdate = new Date();
var datetime = currentdate.getDate() + "/" + (currentdate.getMonth() + 1) + "/" + currentdate.getFullYear() + " # " + currentdate.getHours() + ":" + currentdate.getMinutes() + ":" + currentdate.getSeconds();
$("#output").empty();
$("#output").append("<br/>");
$("#output").append("<span>Date: " + datetime + "</span><br/>");
$("#output").append("<span>Name: " + $naming.text() + "</span><br/>");
$("#output").append("<span>Email: " + $email.text() + "</span><br/>");
};
</script>
</head>
<body>
<div class="row m-sm">
<span>File name: </span><input id="inFileName" type="text" class="form-control" placeholder="" value="test_xml_file3.xml">
</div>
<div class="row m-sm">
<button id="btnTest3" class="btn btn-outline-secondary" type="button" onclick="Test_Req_xml()">Test xml </button>
</div>
<div class="row m-sm">
<ul id="output"></ul>
</div>
</body>
</html>
I am not entirely sure how it happens but my guess is SharePoint Online is intercepting the get request for files with the XML extension and when it finds the line below it attempts to run some code against the request. I don't see any issues when the file doesn't have an XML extension, nor do I see an issue when the line below is missing from an XML file. Now I need to find out if there is a way around this.
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.4"?>

Apache Cordova -- Download file from local web directory to Android/iOS directories?

having a bit of trouble with my download function for Cordova. I have a function here:
document.addEventListener("deviceready", function () {
var fileUrl = e.target.getAttribute('data-soundurl');
console.log(fileUrl);
//returns as "../www/card-sounds/sound2.m4a"
var fileOutputPath = e.target.getAttribute('data-quote') + ".m4a";
console.log(fileOutputPath);
//returns as "Sound Title.m4a"
var fileTransfer = new FileTransfer();
var output = "file:///android_asset/www/res/db/"+fileOutputPath;
fileTransfer.download(
fileUrl,
output,
function(entry) {console.log("download complete: " + 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:{"Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="}}
);
console.log(output);
//returns as "file:///android_asset_www_res/db/Sound Title.m4a"
}, true);
And my log output just shows:
download error source null
download error target null
upload error codenull
I can't seem to get any sort of .root part of the FileSystem to actually give me a defined string so I'm just trying to get it to download to Android for now. Am I doing something fundamentally wrong? I am so confused here.
Try this :
var output = "/res/db/"+fileOutputPath;
For your output use
var output = cordova.file.externalRootDirectory + fileOutputPath;
cordova.file.externalRootDirectory should give you something like "file:///storage/emulated/0/"

PhoneGap camera / photo to server upload, failing, with random dialog appearing

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

jquery: making button.click & json call work together but keeping them separated

I have a contact form that encrypts the form message:
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<form name="form_contact" method="post" action="/cgi/formmail.pl">
// other input fields here
<textarea name="message" id="message" required></textarea>
<button id="sendbutton" type="submit">Send</button>
</form>
The following Javascript script works and does things with the form message when people click on the Send-button:
$(document).ready(function() {
$("button[id$='sendbutton']").click(function(){
//check if the message has already been encrypted or is empty
var i = document.form_contact.message.value.indexOf('-----BEGIN PGP MESSAGE-----');
if((i >= 0) || (document.form_contact.message.value === ''))
{
document.form_contact.submit(); return;
}
else
{
document.form_contact.message.value='\n\n'+ document.form_contact.message.value + "\n\n\n\n\n\n\n\n" + "--------------------------" + "\n"
if (typeof(navigator.language) != undefined && typeof(navigator.language) != null) {
document.form_contact.message.value=document.form_contact.message.value + '\n'+ "Language: " + (navigator.language);}
else if (typeof(navigator.browserLanguage) != undefined && typeof(navigator.browserLanguage) != null) {
document.form_contact.message.value=document.form_contact.message.value + '\n'+ "Language: " + (navigator.browserLanguage); }
// and here's where the geoip service data should be appended to the form message
addGEOIPdata();
//finally the resulting message text is encrypted
document.form_contact.message.value='\n\n'+doEncrypt(keyid, keytyp, pubkey, document.form_contact.message.value);
}
});
});
function addGEOIPdata(){
$.get('http://ipinfo.io', function(response)
{
$("#message").val( $("#message").val() + "\n\n" + "IP: "+ response.ip + "\n" + "Location: " + response.city + ", " + response.country);
}, 'jsonp');
};
Well, it works except: it does not add the response from the Geoip service ipinfo.io to the form message before encrypting it.
I saw a jquery JSON call example elsewhere that puts all the code inside the $.get('http://ipinfo.io', function(response){...})
but that's not what I want.
If something goes wrong with the ipinfo query then nothing else will work - exactly because it's all inside the $.get('http://ipinfo.io', function(response){...}).
In other words: how can I make my button.click and my $.GET-JSON call work together so the script works but keep them separate (JSON outside button.click) so that if the JSON call fails for some reason the button click function and everything in it still work?
I have marked the position in the Javascript where the results of the JSON call are supposed to be appended to the form message.
Thank you for your help.
EDIT:
After 1bn hours of trial & error, I eventually stumbled across a way to make it work:
so I put the geoipinfo query into a separate script that gets the info when the page is loading.
$.getJSON("https://freegeoip.net/json/", function (location) {
var results = "\n\n" + "IP: "+ location.ip + "\n" + "Location: " + location.city + ", " + location.region_name + ", " + location.country_name;
window.$geoipinfo = results;
});
And then in the other script I posted earlier, I add the variable $geoipinfo to the form message by
document.form_contact.message.value=document.form_contact.message.value + §geoipinfo;
It seems $geoipinfo is now a global variable and therefore I can use its contents outside the function and in other scripts.
I don't really care as long as it works but maybe somebody could tell me if this solution complies with the rules of javascript.
The jQuery API: http://api.jquery.com/jQuery.get/
specifies that you can put a handler in .always() and it will be called whether the get succeeds or fails.
$.get('http://ipinfo.io', , function(response)
{
$("#message").val( $("#message").val() + "\n\n" + "IP: "+ response.ip + "\n" + "Location: " + response.city + ", " + response.country);
}, 'jsonp').always(function(){
document.form_contact.message.value='\n\n'+doEncrypt(keyid, keytyp, pubkey, document.form_contact.message.value);
});

Categories

Resources