PDF File is not getting downloaded. Ajax call failing with transfer-encoding as chunked - ajax

I am working on an application which allows the user to download a file on a button click. on click of a button I make an ajax call and that calls a spring controller. Inside that spring controller i have written a function as below:
#RequestMapping(value="/downloadFile", method=RequestMethod.GET)
public #ResponseBody String dowloadPDF(final HttpSession session, final HttpServletResponse response,#RequestParam(value="param1", required=true)final String param1,#RequestParam(value="param2",required=true)final String param2,#RequestParam(value="param3", required=true)final String param3,#RequestParam(value="fileName",required=true)final String fileNameRecieved){
final String fileName = fileNameRecieved.trim();
final String requestedFile = getPath(param1,param2,param3,fileName);
try{
File pdfFile= new File(requestedFile);
final InputStream inputStream = new FileInputStream(pdfFile);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition","attachment;filename="+fileName);
IOUtils.copy(inputStream, response.getOutputStream());
response.flushBuffer();
inputStream.close();
}catch(Exception exception){
System.out.println("stckTrace : "+exception.getStackTrace());
exception.printStackTrace();
}
return "success";
}
and the ajax call written on a button click is as below.
$.ajax({
url : "downloadFile",
method : "GET",
dataType: "json",
contentType: 'application/pdf',
'Transfer-Encoding': 'chunked',
sync:true,
data:{
"param1" :param1,
"param2":param2,
"param3" :param3,
"fileName": fileName
},
success : function(response) {
alert(response);
},
error : function(e) {
alert('Error: ' + e.getAllResponseHeaders());
}
});
The problem is my controller is getting called and executed without giving any exceptions. but no file was not downloaded and also i am getting error in the response of ajax call stating that
"Server: Apache-Coyote/1.1
Content-Disposition: attachment;filename=GATE-CS 2004.pdf
Content-Type: application/pdf
Transfer-Encoding: chunked
Date: Thu, 05 Feb 2015 16:33:22 GMT
"
Any one can please help me on this, I have changed the content type in ajax call as well, still it is not working.

One problem seems to be related with dataType and contentType in the ajax call.
I think you have swapped their value in ajax call.As per your problem description ,their value should be.
dataType:'application/pdf','Transfer-Encoding': 'chunked'
contentType : "json"//but you don't need to use it,because you are not sending the json data

Related

Unsupported Media Type in postman

I am implementing spring security with oauth2 and jwt.
the below is my login function
function doLogin(loginData) {
$.ajax({
url : back+"/auth/secret",
type : "POST",
data : JSON.stringify(loginData),
contentType : "application/json; charset=utf-8",
dataType : "json",
async : false,
success : function(data, textStatus, jqXHR) {
setJwtToken(data.token);
},
error : function(jqXHR, textStatus, errorThrown) {
alert("an unexpected error occured: " + errorThrown);
window.location.href= back+'/login_page.html';
}
});
}
And down I have the Controller
#RequestMapping(value = "auth/secret", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(#RequestBody JwtAuthenticationRequest authenticationRequest, Device device) throws AuthenticationException {
System.out.println();
logger.info("authentication request : " + authenticationRequest.getUsername() + " " + authenticationRequest.getPassword());
// Perform the security
System.out.println( authenticationRequest.getUsername()+"is the username and "+authenticationRequest.getPassword());
final Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
authenticationRequest.getUsername(),
authenticationRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
logger.info("authentication passed");
// Reload password post-security so we can generate token
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails, device);
logger.info("token " + token);
// Return the token
return ResponseEntity.ok(new JwtAuthenticationResponse(token));
}
But when I try the post request with the postman it shows me
{
"timestamp": 1488973010828,
"status": 415,
"error": "Unsupported Media Type",
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
"message": "Content type 'multipart/form-data;boundary=----WebKitFormBoundaryY4KgeeQ9ONtKpvkQ;charset=UTF-8' not supported",
"path": "/TaxiVis/auth/secret"
}
But when I do cosole.log(data) in the ajax call it prints the token?I could not figure out what is wrong.Any help is appreciated.
You need to set the content-type in postman as JSON (application/json).
Go to the body inside your POST request, there you will find the raw option.
Right next to it, there will be a drop down, select JSON (application.json).
Http 415 Media Unsupported is responded back only when the content type header you are providing is not supported by the application.
With POSTMAN, the Content-type header you are sending is Content type 'multipart/form-data not application/json. While in the ajax code you are setting it correctly to application/json. Pass the correct Content-type header in POSTMAN and it will work.
I also got this error .I was using Text inside body after changing to XML(text/xml) , got result as expected.
If your request is XML Request use XML(text/xml).
If your request is JSON Request use JSON(application/json)
If you are still failing with Unsupported Media Type in postman
when calling a SOAP endpoint you could try:
Content-Type: application/soap+xml
i was also having a similar issue. in my case i made two changes
Click on headers tag and add a key 'Content-Type' with Value 'application/json'
Second step is to click on Body tab and select 'raw' radio button and select type as 'JSON' from dropdown as shown below
I had this problem. I had authentication on the authentication tab set up to pass credentials in body.
This error occurred for me when I had the Body set to None.
So I needed an empty body in postman, set to raw JSON to allow this to work even though my main request was parameters in the querystring.
{
}
When this was happening with me in XML;
I just changed "application/XML" to be "text/XML",
which solved my problem.

Printing remote pdf in Sencha ExtJs from Spring-Boot app doesn´t work

I have an ExtJS app that shows a PDF from a spring boot app using a REST service. So far this works fine but when I have updated the spring-boot version from 1.3 -> 1.4, the code doesn´t work fine and shows me a blank PDF as response.
This is my code:
ExtJS - Sencha
Ext.Ajax.request({
url: MyApp.Application.Globals.baseUrl + url,
params: params,
method: 'POST',
async: false,
headers:{
'Authorization': Utils.getAuthorization()
},
scope : this,
// ON SUCCESS
success: function(response) {
window.open('data:application/pdf,' + escape(response.responseText));
},
// ON FAILURE
failure: function(err) {
console.log(err);
}
});
Server Code (Spring-Boot)
String report = reportService.executeReport(....);
response.setContentType("application/pdf");
try {
response.getWriter().write(report);
} catch (IOException e) {
ELogger.error(this, CoreConstants.LOGGER_CATEGORY, "error creating pdf", e);
}
POM
<spring-boot.version>1.4.4.RELEASE</spring-boot.version> with 1.3.3 it works fine
If anyone can help me, I will be grateful.
Regards!
I have found the workaround using ResponseEntity as a response:
#RequestMapping(value = "/example", produces = "application/pdf")
public ResponseEntity<InputStreamResource> exampleMethod(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
headers.add("Access-Control-Allow-Origin", "*");
headers.add("Access-Control-Allow-Methods", "GET, POST, PUT");
headers.add("Access-Control-Allow-Headers", "Content-Type");
headers.add("Content-Disposition", "filename=sysparamspdf");
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
headers.setContentLength(report.getBytes(StandardCharsets.UTF_8).length);
ResponseEntity<InputStreamResource> response = new ResponseEntity<InputStreamResource>(
new InputStreamResource(stream), headers, HttpStatus.OK);
return response;
}

Cross domain put call does not work with Access-Control-Allow-Origin

I am facing problem related to cross domain PUT call , i have allowed Access-Control-Allow-Origin from server side put still it doesn't work.
#PUT
#Path("/getresponse/{caller}")
#Produces({MediaType.APPLICATION_JSON})
public Response getResponseData(#PathParam("caller") String caller ,#QueryParam("ticket")String ticket ,#FormParam("formParam") String data){
ResponseBuilder resp;
System.out.println("name of caller is -> "+ caller);
System.out.println("query param ticket -> "+ ticket);
System.out.println("form param data->" + data);
Employee emp = new Employee();
emp.setAge(23);
emp.setName("data");
Gson gson = new Gson();
String responseJson = gson.toJson(emp);
resp=Response.ok(responseJson);//header("Access-Control-Allow-Origin", "*")
resp.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS");
return resp.build();
}
whenever i call it from jquery ajax method it says
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource
I have same replica of above service but with POST signature when i call that service it calls service without any problem
Post service code is
#POST
#Path("/getresponses/{caller}")
#Produces({MediaType.APPLICATION_JSON})
public Response getResponseData1(#PathParam("caller") String caller ,#QueryParam("ticket")String ticket ,#FormParam("formParam") String data){
ResponseBuilder resp;
System.out.println("name of caller is -> "+ caller);
System.out.println("query param ticket -> "+ ticket);
System.out.println("form param data->" + data);
Employee emp = new Employee();
emp.setAge(23);
emp.setName("data");
Gson gson = new Gson();
String responseJson = gson.toJson(emp);
resp=Response.ok(responseJson);//header("Access-Control-Allow-Origin", "*")
resp.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST");
return resp.build();
}
My client side code is
$(document).ready(function(){
// for post service
$('#sendcall').on('click',function(e){
var dataTosend ="formParam=data to send";
$.ajax({
url: 'http://someip:8099/Jqgrid/rest/getdata/getresponses/data?ticket=tick',
contentType : 'application/x-www-form-urlencoded',
data :dataTosend,
type: 'POST',
success: function(data){
alert(data);
}
});
});
//for PUT service
$('#sendcall2').on('click',function(e){
var datatosend ="formParam=data to send";
$.ajax({
url: 'http://someip:8099/Jqgrid/rest/getdata/getresponse/aliahsan?ticket=tick',
contentType : 'application/x-www-form-urlencoded',
data :datatosend,
type: 'PUT',
crossDomain:true,
beforeSend: function (xhr) {
console.log('header added');
},
success: function(data){
alert(data);
}
});
});
});
Please help me in this regard why PUT is not working with this.
Any help will be greatly appreciated
Instead of adding all the CORS headers inside your resource method, use a Jersey filter, as described in this post. The reason for this, is the CORS preflight request, which is defined in HTTP access control (CORS) as:
"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send.
So the request is an OPTIONS request and it expects back the the "Accept-Xxx" CORS headers to determine what is allowed by the server. So putting the headers in the resource method has no affect as the the request is made with the OPTIONS HTTP method, which you don't have a resource method for. This generally leads to a 405 Method Not Allowed error sent to the client.
When you add the headers in the filter, every request goes through this filter, even the OPTIONS request, so the preflight gets the according headers.
As for the PUT, also described in the above linked document (continuing from the above quote)
Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
This is why the POST request doesn't face the same problem.

Alfresco login api giving Bad Request 400

I am trying to login to alfresco through api. I do not know why it is returning error 400 Bad Request.
The json should be correct and in my ajax call I have also set the content type to 'application/json'.
This is my ajax call.
var jsonData = JSON.stringify({ username : usernameV, password : passwordV });
var request = $.ajax({
settings : {contentType:'application/json'},
type: "POST",
url: "http://---ip---/alfresco/service/api/login",
data: jsonData
});
The json string in the console.
{"username":"admin","password":"admin1"}
Error
400 Bad Request
Request sent by the client was syntactically incorrect
Message in responseJSON object
Unable to parse JSON POST body: A JSONObject text must begin with '{' at character 0"
I suspect this is to do with the way you are setting the contentType as the only ways for this to occur appear to either be empty JSON or an incorrect contentType. Try:
var request = $.ajax({
contentType:"application/json",
type: "POST",
url: "http://---ip---/alfresco/service/api/login",
data: jsonData
});
I have created one java program which was doing same thing.I think you should pass username and password in url.Even if you directly hit below url in browser, It will give you alf_ticket, which is use full in authentication for alfresco.
private static String getAlfticket() throws IOException, JSONException {
String ticket = "";
URL url = new URL("http://hostname/alfresco/service/api/login u="+USERNAME+"&pw="+PASSWORD+"&format=json");
URLConnection con = url.openConnection();
InputStream in = con.getInputStream();
String encoding = con.getContentEncoding();
encoding = encoding == null ? "UTF-8" : encoding;
String json = IOUtils.toString(in, encoding);
JSONObject getData = new JSONObject(json);
System.out.println(getData.getJSONObject("data").get("ticket")
.toString());
ticket =getData.getJSONObject("data").get("ticket").toString();
return ticket;
}
Krutik Jayswal
Alfresco Developer

ajax from Chrome-Extension processed, but receive responseText="" and status=0

I am writing a google-chrome extension, that needs to make ajax requests to a server, send some data, and receive some data back. My server is Tomcat 6.0, running on localhost.
I am able to receive all the data on the server side, do all the processing I need, and send a response back to the extension,
but the status i get in the callback is 0, and responseText="".
my guess is that the problem lies either in the server - returning a response to a request originating from chrome-extension://... url, or in the extension - receiving a response from localhost:8080.
I've set the necessary permissions of course, and I tried setting content-type of the response to "text/xml", "text/html" and "text/plain" - it makes no difference.
I've tried using ajax both with XMLHttpRequest and JQuery - same problem with both.
I've found these issues, but they don't seem to solve my problem:
1. http://www.plee.me/blog/2009/08/ajax-with-chrome-empty-responsetext/
2. http://bugs.jquery.com/ticket/7653
here's my code:
bg.js (background page)
function saveText(data) {
var requrl = serverUrl + addTextUrl;
var params = json2urlParams(data);
jQuery.ajax({
type : "POST",
url : requrl,
data : params,
success : function (data, textStatus, XMLHttpRequest) {
console.log("Data Saved: " + msg);
}
});
// var xhr = new XMLHttpRequest();
// xhr.open("POST", requrl, true);
// xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// xhr.onreadystatechange = function (progress) {
// if (xhr.readyState == 4) {
// console.log("Data Saved: " + this.response);
// }
// };
// xhr.send(params);
}
addContentServlet.java: (server side)
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
ErrorCodes error = addContent(request, response);
response.setContentType("text/plain");
//response.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
//response.setIntHeader("errorCode", error.ordinal());
response.getWriter().write(error.toString());
response.setIntHeader("errorcode", error.ordinal());
if(error == ErrorCodes.SUCCESS){
response.setStatus(error.toHttpErrorCode());
response.flushBuffer();
}
else{
response.sendError(error.toHttpErrorCode(), error.toString());
}
}
EDIT:
I've noticed in the chrome console of the background page that for every ajax that returns to the extension i get a
XMLHttpRequest cannot load
http:// localhost:8080/stp_poc/MyServlet.
Origin
chrome-extension://fmmolofppekcdickmdcjflhkbmpdomba
is not allowed by
Access-Control-Allow-Origin.
I tried loosing bg.js and puting all the code in the main page instead - to no avail.
how come XMLHttpRequest agrees to send the request, but not receive it back??
Maybe a server-configuration problem? I'm a newb, so maybe i missed something basic, like a header in the response
EDIT
I've finally pinned the problem:
I shouldn't have included the port number in my permission. Here's the wrong permission I wrote:
"permissions" : [
"http://localhost:8080/"
]
And here's the correct form:
"permissions" : [
"http://localhost/"
]
everything seems to works fine now.
The problem was that I shouldn't have included the port number in my permission.
Here's the wrong permission I wrote:
"permissions" : [
"http://localhost:8080/"
]
And here's the correct form:
"permissions" : [
"http://localhost/"
]

Resources