javaapache-httpclient-4.xjasperserver

How to download a file from another GET call using Apache Http?


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
    }
}

Solution

  • 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.