How to call SAML (http-post binding) based REST APIs using Angular? - java

I have OData REST APIs protected with SAML 2.0(POST binding) and I have Angular 2+ client application. How can I call these REST APIs using Angular application?
When I use Angular HTTP client
import {Http, RequestOptions, Request, RequestMethod} from '#angular/http';
I'm getting form with continue button to Note:Since your browser does not support JavaScript, you must press the Continue button once to proceed.
If I hit same REST API URL directly in browser, then browser redirects to IDP and then, after successful authentication, IdP redirects back it to REST API.
The same behavior is observed on Postman, but they are fixing it by enabling JS script preview.
Here is Angular code which i tried:
this.POST('https://<RESTAppfqdn>/odata', {"ID": "2"}).subscribe(data => {
console.log(data)
})
}
POST(url, data) {
const headers = Object.assign({
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json;vnd.ptc.ilm.webui2.0=true;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
});
var requestoptions = new RequestOptions({
method: RequestMethod.Post,
url: url,
headers: headers,
body: data
})
return this.http.request(new Request(requestoptions))
.pipe(map(res => res.json()));
}
Here is response I can see in browser's network tab:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
</head>
<body onload="document.forms[0].submit()">
<noscript>
<p>
<strong>Note:</strong> Since your browser does not support JavaScript,
you must press the Continue button once to proceed.
</p>
</noscript>
<form action="https://<Idpfqn>:9031/idp/SSO.saml2" method="post">
<div>
<input type="hidden" name="SAMLRequest" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJodHRwczovL0tJU0pBREhBVjJMMS9zYW1sL1NTTyIgRGVzdGluYXRpb249Imh0dHBzOi8va2lzamFkaGF2MmwxLnB0Y25ldC5wdGMuY29tOjkwMzEvaWRwL1NTTy5zYW1sMiIgRm9yY2VBdXRobj0iZmFsc2UiIElEPSJhM2UzOTMyZjAzNTNmNWI3NTFoYmc4ZWpmY2lkNTViIiBJc1Bhc3NpdmU9ImZhbHNlIiBJc3N1ZUluc3RhbnQ9IjIwMTktMDQtMjVUMDY6MTc6MjUuOTQzWiIgUHJvdG9jb2xCaW5kaW5nPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YmluZGluZ3M6SFRUUC1QT1NUIiBWZXJzaW9uPSIyLjAiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHBzOi8vS0lTSkFESEFWMkwxL3NhbWwvbWV0YWRhdGE8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz48ZHM6UmVmZXJlbmNlIFVSST0iI2EzZTM5MzJmMDM1M2Y1Yjc1MWhiZzhlamZjaWQ1NWIiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIi8+PGRzOkRpZ2VzdFZhbHVlPlNDc3dxRG5FTThNWEJvSnZkRGhrdEE3dGF5VT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+YkxTd3pjRFhYUmNQV1VYa2hHbXB4RXZEQ3JlRWFpc2tka2drTzl5eGpkdGFlalhnSEVBNHRQNWhuL2FyRVh4T0NxWHlmWnFBRXFZZFduTE5vODJyNXZoQ1F2SGhWdEJHTUY0T1FSbXlDT2FwUHRPamdINWtpRW1uaVVHNHduaEpERCsxRWR3L2x2ZFlJd0svSEhCSE8zV2p4eTZ3aW9hbUhMRGczYWNNM0QzdHNMMFR0VlM0RVZETncxeFBmeTdUWTd6WVZqYWUrcmZqRm9IZUlEQlZYdFNnS2xSL2RHbW1DMXBaTDFydWVsZHkzSEJRV3dYVWx5S1NRa09oNU9VWnBCeWttMHBERDhmNnA4UVV3Uy8zTEtxd3hvc1NiWlVIMlJoUHI0RFIwTDMwQjNzSmlka1JKMGI0eUdHNlFzZnlGY3lVZERxdHVDS3FhVkpMR1htSXNnPT08L2RzOlNpZ25hdHVyZVZhbHVlPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURYVENDQWtXZ0F3SUJBZ0lFVXZvcnFEQU5CZ2txaGtpRzl3MEJBUXNGQURCZk1Rc3dDUVlEVlFRR0V3SnBiakVMTUFrR0ExVUUNCkNCTUNiV2d4RFRBTEJnTlZCQWNUQkhCMWJtVXhEREFLQmdOVkJBb1RBM0IwWXpFUE1BMEdBMVVFQ3hNR2NIUmpibVYwTVJVd0V3WUQNClZRUURFd3hMU1ZOS1FVUklRVll5VERFd0hoY05NVGt3TkRJME1UZzBOekV3V2hjTk1qQXdOREU0TVRnME56RXdXakJmTVFzd0NRWUQNClZRUUdFd0pwYmpFTE1Ba0dBMVVFQ0JNQ2JXZ3hEVEFMQmdOVkJBY1RCSEIxYm1VeEREQUtCZ05WQkFvVEEzQjBZekVQTUEwR0ExVUUNCkN4TUdjSFJqYm1WME1SVXdFd1lEVlFRREV3eExTVk5LUVVSSVFWWXlUREV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcNCmdnRUtBb0lCQVFDblM2MmdHQ2llcHZJMXFVdCt4a1d1bjJRenlUWUlLay9DQ0w3WkxVUlkyVmluS0w4UUFGb0xnM0s2bGJCaTVPeEENCjI2em9ZY3cyVHJ5a1FmL2ZuSG04eXpEVWJWSzlmZ0NXVXBzT2tOZnUyMHVZUzc2cTBna0tmbGFFR2Q4UzFFUStVUGMvT0pkem5NTXMNCkpzckZldXZYMVpqZFMzWG9mZlBDZXcvOGdIQzR2dTU1V0tGSDhvODUxQWdRdXRrNzlUYUpYUm5zN0VpUVhvMkVBVnNTUWIrZXpoWGYNCnJuYXNMN1BhUGFWT0JQV1RBTi83VERSZEs4R1RiUHRrWG8wMnIxZnNoZk5rRW05VDhROTBFNmtmU1l6emt3MXByRktwY1RncTZsbmUNClFFMk4zNEpCVTdjUHlYVW8yRHVNNkxVVXZndWFLK2xDK05TamZENWliMFNTcDdtdkFnTUJBQUdqSVRBZk1CMEdBMVVkRGdRV0JCU28NCmxUS3d3dkoxdzBsZjkwZURPWTluUlY4bjJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFYRzA4ZWphdjQxYWJtQS9jZkNZUFQrWVINClhQSnZzQ1F1YTJRempRSy9IMDdNclJsOTVCSkkzeUJEQ1pJaW9ndU5YbS9sbHVxYzV1VWJtekdBenBFM3MybnZtbjQ0bjBhUVYyd28NCkxja2NiWUZJUkNFRFhOZXFZUEUrZFVGdVgwSEJ5dlFqNU9FSU9wZTlYTzUrZ1lFUUlXZWxTZXFibUF0UmRuWi84ZWlFY3h6bEFaTlINCkRITDlxdjloK2doNFpPM3BkRVNLdWM3Z0NKODFXVGNueUN1QS9ZS1ZMR2lnM0plbEJJYkhwZTVXcXBaR3dPUG9WYk82cVViTzlHQjUNCmxVQkxYRlF3cmVSazlTV3JVQkV5Wi8yQ3ovY1UvVjRnSms4cGdTWTFPVHNOUmpGanZKVjd1TnBQeEsxam1nRkRsakV5aXpHay96WGENClJDNjE1VVhIbExpb093PT08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48L3NhbWwycDpBdXRoblJlcXVlc3Q+"/>
</div>
<noscript>
<div>
<input type="submit" value="Continue"/>
</div>
</noscript>
</form>
</body>
</html>```
As Angular http client reside in browser, browser should take care of handling this post form submission and redirection work but that is not happening. Is there any way by which i can tell browser to handle such responses?

As there is form in response received from server, I have submit that form.
Hence, I have created a div (ex. auth) in index.html and when the response contains the form then submit that. Here is that code.
if (res['error']['text']) {
let authDiv = document.getElementById('auth')
authDiv.innerHTML = res['error']['text']
var f1 = authDiv.children[1]
f1.submit()
return new HttpResponseFailAction([res['error']['text']])
}
But then we will face another issues with that:
Ex. The auth challenge received from IdP has to be displayed.
Basically, we need to act like browser and any coming requests we need to handle.
Hence, I decided to discarded this approach and added SAML SSO support to client application itself.

Related

Load spring form by an ajax request in already rendered JSP

Let's say there is a JSP which has been rendered to the client. On this Jsp, I created a link, I want this link to make a request to the server and server sends a spring from with command object in it and this spring form gets rendered on the already loaded page on client. I mean I do not want whole page to be loaded. Let's take a scenario like there is link 'update contact details' on my page. Clicking on this link makes an ajax request to the server and spring form is sent from the server such that form is populated with the contact details of the user who clicked the link of 'update contact details'. Basically I want stuff like header and footer not to be loaded unnecessarily every time.
Thanks in advance.
IF you have a link as,
<a id="screenId" href="#">
then add <div id="container"></div> somewhere you want your page, also a js function as,
$('#screenId').click(function() {
$.ajax({
type: "GET",
cache: false,
url: "yourControllerURL",
data: "",
success: function(response){
$('#container').html(response);
}
});
});
with the above ajax call, inside your controller, return your jsp with the command object. The controller code may look something like this.
#RequestMapping(value="yourControllerURL")
public String includeAnotherJSP(ModelMap model) {
model.addAttribute("commandObjectName", commandObject);
return "yourJSPMapping/jspName";
}
After your controller will send the response, you will get the required JSP inside the response and you can then load that into your <div id="container"> using above js code.

Web services in Django

I have a simple Java application, which reacts to web service request.
When the user presses a button, a message is sent to the Java application.
If the message is "ping", then the application responds with "pong", otherwise - "uknown message".
Code of the Java application:
#Path("/ping-pong")
public class PingPongService {
#POST
#Produces("text/plain")
public String test(#FormParam("message") final String aMessage) {
System.out.println("message from client: " + aMessage);
if ("ping".equalsIgnoreCase(aMessage)) {
System.out.println("ping.equalsIgnoreCase(aMessage)");
return "pong";
} else {
System.out.println("Unknown message");
return "unknown message " + aMessage;
}
}
}
Inside the WAR file, I have following HTML code, which works (when I press one of the buttons, I get the response from the Java application and it is displayed in the message box):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>JavaScript Ping-Pong Client</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
//This function send post request to the server using jQuery
function testWithJQuery(message){
$.post('http://localhost:8345/rest/ping-pong', { message: message }, function(data) {
alert(data);
});
}
//This function send post request to the server using a low-level XmlHttpRequest instead of the jQuery
//(no dependencies on external libraries)
function test(message){
var http = new XMLHttpRequest();
var url = "http://localhost:8345/rest/ping-pong";
var params = "message=" + message;
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
};
http.send(params);
}
</script>
</head>
<body>
<button onclick="test('ping')">Test</button>
<button onclick="testWithJQuery('ping')">Test using jQuery</button>
</body>
</html>
I want to do exactly the same thing (user presses a button, a message is sent to the Java application and its response displayed in an alert message window) in a Django application.
Django generates following HTML code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
//This function send post request to the server using jQuery
function testWithJQuery(message){
$.post('http://localhost:8345/rest/ping-pong', { message: message }, function(data) {
alert(data);
});
}
//This function send post request to the server using a low-level XmlHttpRequest instead of the jQuery
//(no dependencies on external libraries)
function test(message){
var http = new XMLHttpRequest();
var url = "http://localhost:8345/rest/ping-pong";
var params = "message=" + message;
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
};
http.send(params);
}
</script>
</head>
<body>
<button onclick="test('ping')">Test</button>
</body>
</html>
When I press the "Test" button in Django-generated code, the Java application receives the message (I see this in the console output), but the response of the Java application is not displayed in Django web site, even though the HTML code is identical to the one in the WAR file.
How can I fix this, i. e. make sure that the response of the Java application is displayed in Django?
UPD: Here's the detailed error description in the "Network" pane of Chrome:
This is not an straight answer but rather some tips to help you diagnose the problem; I'm posting here because it is too big for a comment.
open the Chrome debugger (shif+ctrl+i) or Firefox Firebug and make the Network tab active.
inspect the post made by both versions and compare headers and body
If there is distinct behavior, there should be some differences between both posts.
[update]
I found the error - see the screenshot in the question. The error is "XMLHttpRequest cannot load localhost:8345/rest/ping-pong. Origin localhost:8000 is not allowed by Access-Control-Allow-Origin.".
The error is due to security constraints in the browser (same origin policy). There are some workarrounds (source: wikipedia):
To enable developers to, in a controlled manner, circumvent the same origin policy, a number of "hacks" such as using the fragment identifier or the window.name property have been used to pass data between documents residing in different domains. With the HTML5 standard, a method was formalized for this: the postMessage interface, which is only available on recent browsers. JSONP and cross-origin resource sharing can also be used to enable ajax-like calls to other domains.2 easyXDM can also be used to easily work around the limitation set in place by the same origin policy. It is a lightweight, easy-to-use and self-contained Javascript library that makes it easy for developers to communicate and expose javascript APIs across domain boundaries.
I've used the subdomain hack with success, see this answer:
Ways to circumvent the same-origin policy

Updating div with post results using radio button and jquery/Ajax

I'm working with a third party that is generating div content based on a post response from my server (java servlet). One problem I have is that we have a list of radio buttons leveled in a form.
When I hit submit on that form, I need to make a post call to my server and re-render that div in the third party site. I have used different variations of jQuery to no avail.
I've included the most recent jQuery (also tried a sub 1.4 release of jQuery). When I hit the submit button on my form, I just render the same page and I do NOT render a call to the server.
How can I do this, update a div on the local page that renders my post results based on a form I write? Below is what I currently have:
Form:
<form action='\' id=\"form1\">... radio buttons ... </form>
<input hidden field name = value passed from Java method>
<input hidden field id = value passed from Java method>
<input hidden field the value of the selected checkbox>
HTML:
<script language='Javascript' type='text/javascript'>
$(\"#form1\").submit(function(event) {
event.preventDefault();
var $form = $( this ),
name2= $form.find( 'input[name=\"name\"]' ).val(),
id2= $form.find( 'input[name=\"id\"]' ).val(),
url = $form.attr( 'action' );
$.post( url, { name2:name, id2:id },
function( data ) {
var content = $( data ).find( '#content' );
$( \"#this_div\" ).empty().append( content );
});
});
</script>
Sending AJAX Requests from a Third Party site to your server:
Due to browser security requirements, it is not currently possible to make cross-domain AJAX requests to a third-party server. This means that the $.post request is limited to what is referred to as the same-domain policy.
Thus, if your server is example.com and the third party server is domain.com, domain.com cannot make AJAX requests to your server.
However, there is a technique you can use to circumvent this browser security. While it's not possible for XMLHttpRequests to be made cross domain, JavaScript <script> tag blocks can load JavaScript from any domain.
Script tag remoting, or JSONP, involves using a script tag to send a request to your server:
Script tag:
// from domain.com to your server, example.com, make a request using a script tag
var urlWithParams = "http://example.com/getHTMLForm.do?id2=" + id2 + "&name2" + name2;
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.setAttribute("src", urlWithParams);
// create a script tag, which invokes your servlet
document.getElementsByTagName("head")[0].appendChild(script);
getHTMLForm.do is a hypothetical servlet that you're currently using to post the data and get HTML in the response. Instead of passing the parameters in the Request body using POST, you'll pass the data as query parameters.
Server response::
The server then responds with JSON that you generate on the server, but it's wrapped -- or padded -- inside a JavaScript function that is defined on the web page making the request.
// your response from your server
insertFormOnPage({"html":"<form action='#'><input name='name' /><input name='id' /></form>", "elem" : "#content"});
Third party Client side code:
For this technique to work, the third party site must have a function defined that matches the one your server will return:
function insertFormOnPage( data ) {
alert( data.html ); // prints the HTML for debugging
alert( data.elem ); // prints the selector you want to insert into
// inject the HTML into the #content DIV
$( data.elem ).html( data.html );
}
HTML on the third party site:
<!-- Let's just assume the third party site's DIV is empty for simplicity -->
<div id="#content"></div
Explanation:
Your server returns pure JavaScript to the client side, as JavaScript, as a function that executes immediately.
The function receives the following items as properties in a JavaScript object: The HTML, and the div id.
The function accesses the object's html and elem properties to access both the html string and the selector.
Using jQuery, the function injects the HTML inside the DIV#content element.
The last and final thing you should know about this technique is that it only supports GET methods, since that is how JavaScript is fetched from the server. This means that you'll need to make sure your server is configured to accept GET requests for this data and not POST requests.
JSONP Using jQuery:
While the above solution helps describe the concepts of what is happening under the hood, you may also want to check out jQuery getJSON. Specifically, look at the JSONP examples, which are the only way to make cross-domain requests without reloading the page.
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?",
{
tags: "cat",
tagmode: "any",
format: "json"
},
function(data) {
$.each(data.items, function(i,item){
$("<img/>").attr("src", item.media.m).appendTo("#images");
if ( i == 3 ) return false;
});
});

xmlhttprequest to get encryption key + html form - what am I doing wrong

The final stage of my project is to connect my website to a bank payment gateway to allow people to buy things using credit cards but without storing any credit card data on my site. I've been on Google and stackoverflow and think I'm on the right track but am obviously doing something wrong.
The idea is that as the form opens an http-post happens which sends a set of parameters to the gateway which responds with a nice long encryption string which I use to submit the actual order. I'd appreciate some help here as I'm now quite stuck.
<form method="post" action="/A55D74/fwcdirect.nsf/encrypt?OpenForm&Seq=1" name="_encrypt">
<input type="hidden" name="__Click" value="0" /><form action="https://encryption-gateway-url.e" method="post">
<script>
var url = "valid-url";
var params = "clientid=12&password=xyz&chargetype=Auth&currency=42&total=1.00";
xmlhttp = new XMLHttpRequest();
xmlhttp.open("post", url, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(params);
return xmlhttp.responseText;
</script>
<input type="hidden" name="returnurl" value="http://www.mywebsite.co.uk/">
<input type="hidden" name="merchantdisplayname" value="Website + Shopping cart">
<input type="submit" value="10.00">
</form>
9th April: I still haven't cracked the problem yet although am getting an error response from the gateway server, I'm currently exploring dojo which is looking very promising and as a bonus comes pre-installed with Lotus Notes client & server (Domino 8.5.1 has dojo 1.3.2).
My guess would be you are supposed to do this on the server, not in the client where same-origin policy prevents you from posting and reading data to a different domain.
I.e. The customer loads the final payment page; before its returned from your server you post your billing details to the the bank, get the encrypted response and append that as a hidden field in the form the user will actually submit for payment.
Its supposed to be a way to prevent users from messing about with the client/amount params, they should never see them at all.
(This looks like EPDQ, if so that's definitely what your supposed to do as I use it myself!)
XMLHttpRequest is a callback method, so it means you should create a callback function to process the responseText.
e.g.
var url = "valid-url";
var params = "clientid=12&password=xyz&chargetype=Auth&currency=42&total=1.00";
xmlhttp = new XMLHttpRequest();
xmlhttp.open("post", url, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// add this line
xmlhttp.onreadystatechange = callback
xmlhttp.send(params);
// remove this line
//return xmlhttp.responseText;
// add a new function
function callback(req, id) {
if(req.readyState == 4 && req.status == 200) {
alter(req.responseText);
}
}

how to use multipart to upload file using XMLHttpRequest?

Here is what I am doing
var url_action="/temp/SaveConfig";
var client;
var dataString;
if (window.XMLHttpRequest){ // IE7+, Firefox, Chrome, Opera, Safari
client=new XMLHttpRequest();
} else { // IE6, IE5
client=new ActiveXObject("Microsoft.XMLHTTP");
}
client.onreadystatechange=function(){
if(client.readyState==4&&client.status==200)
{
alert(client.responseText);
}
};
//dataString=document.getElementById("tfile").value;
client.open("POST",url_action,true);
client.setRequestHeader("Content-type", "multipart/form-data");
client.setRequestHeader("Connection", "close");
client.send();
But at the server side i get org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Where am i going wrong?
After reading reply from Aticus
Here is what i did and file is getting uploaded.
var form=document.forms["mainForm"];
form.setAttribute("target","micox-temp");
form.setAttribute("action",url_action);
form.setAttribute("method","post");
form.setAttribute("enctype","multipart/form-data");
form.setAttribute("encoding","multipart/form-data");
form.submit();
but now how do i recieve values from servlet to perform some kind of checking apart from JSON?
Until the upcoming XMLHttpRequest version 2, you cannot upload a file using Ajax.
Most of the current Ajaxbased file uploaders use an <iframe> hack. It uses JS code to create an invisible <iframe> where the form is been copied in and is been submitted synchronously. The parent page will just stay unchanged and it looks like as if it is been done asynchronously.
To get best crossbrowser compatibility and to minimize headaches with regard to writing crossbrowser compatible code, I'd strongly recommend to grab an existing JS library which excels in handling ajaxical stuff and traversing/manipulating HTML DOM tree, such as jQuery. It comes with plethora of form upload plugins, the simplest one being the jQuery-form plugin. It supports file uploads as well with help of the hidden <iframe> hack. It's then basically as easy as
<script src="jquery.js"></script>
<script src="jquery-form.js"></script>
<script>
$(document).ready(function() {
$('#formid').ajaxForm(function(data) {
// Do something with response.
$('#result').text(data.result);
});
});
</script>
...
<form id="formid" action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" />
</form>
<div id="result"></div>
In the server side, just have a servlet which processes the request the usual way, either with the Servlet 3.0 provided HttpServletRequest#getParts() or with the good old Apache Commons FileUpload (examples here).
Either way, you can just return the response as JSON the usual way
Map<String, Object> data = new HashMap<String, Object>();
data.put("result", "Upload successful!");
// ...
response.setContentType("application/json");
resposne.setCharacterEncoding("UTF-8");
resposne.getWriter().write(new Gson().toJson(data));
For more Ajax-Servlet-JSON examples, check this answer.
Files are not transmittable via asynchronous requests such as this. You'll need to submit it in a multipart form.
Depending on what the file is you could store the data in a post variable.

Categories