How to pass FormData over XMLHttpRequest using GET method - javascript

When Method of the senderform is POST, everything works fine. However, as soon as I change the method to GET, I don't receive anything on the server.
function ajaxSubmit(destinationElement, senderform) {
var xmlreq = new XMLHttpRequest();
var params = new FormData(senderform);
xmlreq.open(senderform.method, senderform.action, true);
if (/\/content\.php$/.test(senderform.action))
xmlreq.onreadystatechange = receiveTable;
else xmlreq.onreadystatechange = receiveText;
xmlreq.send(params);
}
I know that I could manually append key-value pairs at the end of Action address, but the problem is that I don't know which form is going to be passed with what fields.
I would prefer native javaScript if possible.
How can I send a GET request using XMLHttpRequest with key-value pairs from senderform which points to form Element (the same way as it already works for POST requests)?

First parameter is a reference to submit button, or form element itself. Second is callback function for XMLHttpRequest.
var ajaxSubmit = function(sender, callback) {
var xmlreq = new XMLHttpRequest(), params;
// look around for the sender form and key-value params
if (sender.form !== undefined)
{
params = new FormData(sender.form);
params.append(sender.name, sender.value);
sender = sender.form;
}
else params = new FormData(sender);
var actAddress = sender.action;
// append the params to the address in action attribute
if (sender.method == 'get')
{
var firstRun = true;
for (var key of params.keys())
{
if (firstRun)
{
actAddress += '?';
firstRun = false;
}
else actAddress += '&';
actAddress += key + "=" + params.get(key);
}
}
xmlreq.open(sender.method, actAddress, true);
xmlreq.onreadystatechange = callback;
if (sender.method == 'get')
xmlreq.send();
else xmlreq.send(params);
}
Therefore you can use it as
<form onsubmit="ajaxSubmit(this,callbackFx)" >
<!-- or -->
<input onclick="ajaxSubmit(this,callbackFx)" type="submit" name="" value=""/>
</form>

Are you sure the problem is not the PHP script? I see no reference that https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#send() with FormData needs POST to work, but if the PHP script takes the info from $POST or something (My PHP is rusty), the behavior would be different.

Since you can't create a useable body in a GET request (see below), then the other option is to use params in the url.
function buildGetUrlParams(baseUrl, paramsObj) {
var builtUrl = baseUrl + "?";
Object.keys(paramsObj).forEach(function(key) {
builtUrl += key + "=" + paramsObj[key] + "&";
});
return builtUrl.substr(0, builtUrl.length - 1);
}
document.getElementById('finalUrl').innerText = buildGetUrlParams('http://test.url.com', { name:'James', occupation:'web design' });
<div id="finalUrl"></div>
An HTTP GET request can contain a body, but there is no semantic meaning to that body. Which means, in simple terms, that a server doesn't have any reason to, nor have any knowledge of how, to process the body of a GET request. If it's possible to write a server that could do this, it would be bad practice as per the HTTP/1.1 specs:
if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.
And that's basically why it's not working. If you want to send any sort of data that the server is able to respond to, then you'll need to use a different HTTP method.
This answer also explains this issue.

Related

How do I upload a file using POST in angular?

How do I transmit a pdf file? I have found multiple ways online, but most of them involve a rework of how our current system works, which is far from ideal.
Im not too familiar with angular, but I am trying to upload a file to the server. i am using existing architecture, so the issue isnt as easy as simply rewriting it from the ground up. Spring complains that "The current request is not a multipart request", if i try to send it as a multipart file, but I dont know how to make it one. The file type must be of type Blob. Currently, no error is thrown, but data.content is empty after the data block is transmitted.
Here is what I currently have:
$scope.uploadPDF = function(uploadedPDF) {
var url = 'uploadPDF';
data = {};
data.comments = $scope.worksheet.comments;
data.queryId = $scope.qId;
data.responseId = $scope.responseId;
data.requestTS = new Date().getTime();
data.content = uploadedPDF;
$http.post(url, data);
};
and the function that calls it is this, it pulls in the file, generates a name and adds the name as a property to be handled serverside, does some unaffiliated logic, then calls the above function for transmission:
$scope.addPDF = function() {
var pdfUploads = document.getElementById('file');
if ('files' in pdfUploads)
{
if (pdfUploads.files.length == 0)
{
$scope.setReasonForChange("addPDF");
}else
{
for (var i = 0; i < pdfUploads.files.length; i++)
{
var currentTimeZone = new Date().toLocaleTimeString('en-us',{timeZoneName:'short'}).split(' ')[2];
$scope.militaryTime = $filter('date')(Date.now(), "MM-dd-yyyy_HHmm");
pdfUploads.files[i].generatedFileName = "QID-" + $scope.queryId + "_" + $scope.worksheet.response.PDF_DESCRIPTION + "_" + $scope.militaryTime + currentTimeZone + ".PDF";
}
}
}
var pdfComment = document.getElementById("pdfComment").value;
if (!pdfComment)
{
$scope.setReasonForChange("updatePDF");
} else
{
var blobPDF = new Blob([pdfUploads.files[0]], {type: 'application/pdf'});
$scope.uploadPDF(blobPDF);
}
}
HTML is:
<form name="UploadForm" id="UploadForm" class="details" form-on-change="formChanged()" enctype="multipart/form-data">
<input type="file" multiple size="50" id="file" name="file" ng-disabled="is_readonly"/>
<button ng-click="addPDF()" ng-disabled="is_readonly">Add</button>
</form>
And lastly, serverside is this, where i think data is part of a linkedhashmap, where the values are taken from in the server, and processed:
#ResponseBody
#RequestMapping(value = "/uploadPDF", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseAttachment uploadPDF(#RequestBody Data data, HttpServletRequest request) throws Exception {
User user = (user) request.getSession(false).getAttribute(FieldConstants.USER_SESSION_ATTR);
ResponseAttachment newPDF = responseAttachmentService.addAttachment(data, user.getUserId());
return newPDF;
Currently, it transmits and receives the data, except the place where the file is supposed to be is empty.
I have attempted ng-fileupload, but attaching it to our product is a nightmare, especially considering that its use kinda requires the user to already know how to use angular as it has little documentation... and we have no angular people.
This question may help you.
Basically you can't send files in purely a JSON format. You have to use a multipart form and post it that way. For example:
postFile(file) {
var postData = new FormData();
postData.append('File', file);
var params = {
headers: {
"Content-Type": undefined
}
$http.post(url, data, params).then([...]);
}
You'll need the extra Content-Type param so that it is sent properly.

Returning JSON from PHP, convert JSON to javascript array, return array from AJAX call

I am working on a project that uses a function I called AjaxRequest which handles all AJAX requests I make. I have no problems in making the request however getting the request back is the issue and placing it where I want it on my page is becoming stressful.
HTML BIT
<body onLoad="calling();">
<div id="status">Status: </div>
</body>
JAVASCRIPT BIT
function calling() {
var answer = ajaxRequest("testing", "test.php", "test=test");
document.getElementById("status").innerHTML += answer[1];
document.getElementById("status").innerHTML += " " + answer[3];
}
function ajaxRequest(app, location, credentials) {
var extras = "";
if(credentials === "" || credentials) {
extras = "&" + credentials;
}
var ajax = ajaxObj("POST", location);
ajax.onreadystatechange = function() {
if(ajaxReturn(ajax) == true) {
var obj = JSON.parse(ajax.responseText);
var arrayObj = [];
for(var i in obj) { arrayObj.push([i, obj[i]]); }
return arrayObj;
}
}
ajax.send("app=" + app + extras);
}
there are two other functions running: ajaxObj and ajaxReturn but I excluded those because they is not the problem. Furthermore, I am trying to make ajaxRequest an efficient function that could be used by more than one application without having to rewrite all the code in more than one location. All error handling acquires before the actual use of ajaxRequest.
PHP BIT
<?php
if($_POST['app'] == "testing") {
$hey = array('success' => 1, 'message' => 'Successful');
echo json_encode($hey);
exit();
}
?>
I'm using calling as a javascript function that does all error handling, this is just basic for the whole of my project however I try to get the JSON from php and convert it to array and the issue is returning the array into calling. I try to display the information on the page yet nothing works.
I am not looking to use any JQuery for my project so I would like to exclude the use of it for this piece of code.
If you want, you could set the header before sending back the json.
header('Content-Type: application/json');
Usually you don't need it, but it will tell your javascript that it's json, and the array will be transform in a javascript object. It work with Jquery, but I assume it'll work without too

Google Analytics - Using GET instead of POST

Ran into an issue where I need to use GET vs POST on a form method, but GATC cookie data is not being appended to the URL correctly, because the form's data is trumping Google's GATC data (using linkByPost).
I've read up on a potential solution posted here, but seems like an insane amount of work to make GET behave. I also stumbled upon another solution here, but IE doesn't respect anything after the 'anchor' portion of the url.
Anyone have any other ideas? If I can't handle this via JS, I will have to go into the script handling the form action and massage the querystring manually (assuming that GATC data is in $_REQUEST array). FTR, GATC data is not available via the $_REQUEST array, when using get.
For future reference, in case anyone runs into the same issue, this is the solution I implemented. I lifted some code from the answer to this SO post, and combined it with the idea behind this post, where it localizes the GATC data, and adds hidden fields to the form for each one.
Resulting code:
$(document).ready(function() {
$('#formId').submit(function(e) {
try {
e.preventDefault();
var form = this;
if (typeof _gat !== 'undefined') {
_gaq.push(['_linkByPost', this]);
var pageTracker = _gat._getTrackerByName();
var url = pageTracker._getLinkerUrl(form.action);
var match = url.match(/[^=&?]+\s*=\s*[^&#]*/g);
for ( var i = match.length; i--; ) {
var spl = match[i].split("=");
var name = spl[0].replace("[]", "");
var value = spl[1];
$('<input>').attr({
type: 'hidden',
name: name,
value: value
}).appendTo(form);
}
}
setTimeout(function() { form.submit(); }, 400);
} catch (e) { form.submit(); }
});
});
You can use jQuery serialize to get the form's elements, then _getLinkerUrl to append the cross-domain tracking data
$('#formID').submit(function(e) {
var pageTracker = _gat._getTrackerByName();
var url = this.action + '?' + $(this).serialize();
url = pageTracker._getLinkerUrl(url);
if (this.target != '_blank') location.href = url;
else window.open(url);
});

How do I handle the *response* when I get one back from an XMLHttpRequest "Post" operation?

I'm having a great deal of difficulty with this - I seem to be going in circles.
What I'm trying to do is POST data to a web service from a javascript on a client.
in the examples below, valFname, valLname, valPhone, and valZip all have valid string values:
function checkOffers(){
// data collection from loaded form...
var postData = "'FirstName':'" + valFname ;
postData +="','LastName':'" + valLname ;
postData +="','PhoneNumber':'" + valPhone ;
postData += "','Zipcode':'" + valZip+"'";
initialize(postData);
}
function initialize(postData) {
//var postMsg = createSoapHeader(msg);
var url = "https://server.company.com:9999/analytics/webservices/webservice.asmx/SamplePriorityOfferList";
request.open("POST", url, false)
request.onreadystatechange = function(){
if(this.readyState===4){
//request is complete. handle it
processData;
}
};
request.send(postData);
}
function processData(){
response = request.responseXML.xml;
alert("Returned Data:" + response);
}
I am calling the checkOffers function on the PageLoad event - I want the web service to fire without having to click a button, link, etc.
I'm getting nulls back from my request, but should be getting data.
Any comments, tips, or suggestions are greatly appreciated.
This line:
if(this.readyState===4){
should be:
if(this.readyState==4){
That should at least get you seeing the alert.

Help me properly make an AJAX call

I have a JavaScript function that is being called. I need to have it call a PHP function and return a true/false.
The script with the function is in the file /db/cancel_hike.php
My current JS looks like this:
function uncancelHike( hike_id )
{
//var url = "/db/cancel_hike.php;
var success = null;
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.open("GET", url , true);
request.onreadystatechange = function()
{
if (request.readyState == 4)
{
var xmlDoc = request.responseXML;
// obtain the array of markers and loop through it
markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++)
{
// obtain the attribues of each marker
success = markers[i].getAttribute("success");
if ( success == "true" )
{
document.getElementById("success").style.display = 'block';
document.getElementById("warning").style.display = 'none';
document.getElementById("error").style.display = 'error';
}
if ( success == "false" )
{
document.getElementById("success").style.display = 'none';
document.getElementById("warning").style.display = 'none';
document.getElementById("error").style.display = 'block';
}
}
}
}
request.send(null);
return false;
}
What I am having trouble with is:
How to call an actual function in the PHP script?
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
I am using YUI JS library. Do I need to make some calls to it, or is it not necessary in this case?
How to call an actual function in the PHP script?
You can't. You request URIs.
Write a PHP script that calls the function you want and place it at the URI you call.
(You can use query strings and the like as the input to an if statement that you use to conditionally call different functions)
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
You can return any kind of data you like.
I am using YUI JS library. Do I need to make some calls to it, or is it not necessary in this case?
It's a library. You never need to make calls to it. It often simplifies the code you have to write.
How to call an actual function in the PHP script?
Do I absolutely need to have some XML returned? Or is there a way to just get back the returned value?
Well, you don't call the actual function. What you want to do is pass variables using GET, that is, by appending them to the URL like file_name.php?var1=this&var2=that to pass var1 of "this" and var2 equaling "that." You retrieve them in the PHP file with $_GET['this'] and $_GET['that']. Whatever PHP outputs to the page via echo, print_r, etc. is then sent back in a request object as part of its responseText property.
You just set url in request.open to a URL on your site. For example, in your .js file:
request.open("GET", "answer_me.php?hike_id=" + hike_id, true);
And in your .php file:
<?php
$hike_id = $_GET['hike_id'];
if ($hike_id < 5) {
echo "true"; // echo true would return "1", BTW
} else {
echo "false"; // echo false would return nothing
}
Note that that will just return a string value to request.responseText of false, thus you could do this:
var result = request.responseText;
if (result === "true") {
...
document.getElementById("success").style.display = "block";
...
} else {
...
document.getElementById("success").style.display = "none";
...
}
You do not need it to be XML, especially as it looks like you're not really using the loop (the same three DOM elements are being assigned values each time).
And honestly, for AJAX I'd recommend using a framework like jQuery (or YUI, although I don't find its AJAX stuff as intuitive). Your entire code would look like this:
var $success = $("#success");
var $error = $("#error");
function cancelHikeCallback(data) {
var is_success = (data === "true");
$success.toggle(is_success);
$error.toggle(!is_success);
}
function cancelHike(hikeIdToSend) {
$.get("/db/cancel_hike.php", {hike_id: hikeIdToSend}, cancelHikeCallback);
}
IMO things like jQuery's $.ajax ($.get is a specialized form of $.ajax) make this stuff much easier to read and debug.
jsFiddle Example

Categories