I'm trying to download a file from my local Jasper server using REST API:
http: // : / jasperserver [-pro] / rest_v2 / reportExecutions / requestID / exports / exportID / outputResource
My interest is that I want to prevent my client from saving a file on the server, I want a direct download using the output from the previous GET call (as a small bridge, nothing more).
I have been using the Apache Http API to do this. Previously I had to make other calls to authenticate, to request the resource and now .... download it.
My problem is that when I download the file, it comes with 0kb and the browser reports that the file is corrupted (it is a pdf that I want to download).
This is the code I'm using to download the file.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String pass = request.getParameter("pass");
String fileType = "pdf"; // request.getParameter("type") pdf o xls
CloseableHttpClient httpClient = HttpClients.createDefault();
CookieStore cookieStore = new BasicCookieStore();
HttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);
List<NameValuePair> urlParameters = new ArrayList<>();
urlParameters.add(new BasicNameValuePair("j_username",username));
urlParameters.add(new BasicNameValuePair("j_password",pass));
boolean valid = executeAuthenticationValidation(urlParameters,response,httpClient,httpContext);
if(valid) {
ReportObject repObj = requestJasperReport(request.getParameter("params"),fileType,response,httpClient,httpContext);
if(repObj != null) {
String requestId = repObj.requestId;
String exportId = repObj.exports.get(0).id;
HttpGet get = new HttpGet("http://localhost:8081/jasperserver/rest_v2/reportExecutions/"+requestId+"/exports/"+exportId+"/outputResource");
int rescod;
HttpEntity content;
String name;
String filetype;
try (CloseableHttpResponse chres = httpClient.execute(get,httpContext);) {
StatusLine status = chres.getStatusLine();
rescod = status.getStatusCode();
name = chres.getFirstHeader("Content-Disposition").getValue().split(";")[1];
filetype = chres.getFirstHeader("Content-Type").getValue();
content = chres.getEntity();
}
if(rescod==200) {
response.setContentType(filetype);
response.setHeader("Content-disposition", name);
try (InputStream in = content.getContent();
OutputStream out = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int numBytesRead;
while ((numBytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, numBytesRead);
}
}
httpClient.close();
}
}
} else {
// Error
}
}
Ok, Lol my bad, this happens when you don't control properly the Try-catch with Resources. Just had to move some code inside of the Try block:
if(repObj != null) {
String requestId = repObj.requestId;
String exportId = repObj.exports.get(0).id;
HttpGet get = new HttpGet("http://localhost:8081/jasperserver/rest_v2/reportExecutions/"+requestId+"/exports/"+exportId+"/outputResource");
HttpEntity content;
String name;
String filetype;
try (CloseableHttpResponse chres = httpClient.execute(get,httpContext);) {
StatusLine status = chres.getStatusLine();
name = chres.getFirstHeader("Content-Disposition").getValue().split(";")[1];
filetype = chres.getFirstHeader("Content-Type").getValue();
content = chres.getEntity();
if(status.getStatusCode()==200) {
response.setContentType(filetype);
response.setHeader("Content-disposition", name);
response.setHeader("Content-Length", String.valueOf(content.getContentLength()));
try (InputStream in = content.getContent();
OutputStream out = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int numBytesRead;
while ((numBytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, numBytesRead);
}
}
httpClient.close();
}
}
}
} else {
// Error
}
I was getting 0kb because the InputStream was closing it early.