PDF file returned from serveResource does not render

thumbnail
Jamie Sammons, modified 2 Years ago. Regular Member Posts: 225 Join Date: 4/7/11 Recent Posts

I have a FreeMarker portlet that invokes a method that creates a PDF file using iTextPDF.  I know the file is created succesfully because I can navigate to the location and doubleclick and open it. So, I created some code to return the file to the browser:

	@Override
	public boolean serveResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse)
			throws PortletException {
		
		String body = "";
		
		// Just to get a request object we can work with
		HttpServletRequest httprequest = PortalUtil.getHttpServletRequest(resourceRequest);
		HttpServletRequest osr = PortalUtil.getOriginalServletRequest(httprequest);
		HttpServletResponse httpresponse = PortalUtil.getHttpServletResponse(resourceResponse);

		String fileRef = "/mydata/data/iTextTable.pdf";
		
        File downloadFile = new File(fileRef);

        // modifies response
        httpresponse.setContentType("application/pdf");
        httpresponse.setContentLength((int) downloadFile.length());
        
        String headerValue = String.format("inline; filename=\"%s\"", fileRef);
        
        // set caching to no cache by whatever means you can.
        httpresponse.addHeader("Content Disposition", headerValue);
        httpresponse.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        httpresponse.setHeader("Pragma", "no-cache");
		String fileRef = BASE_DATA_PATH + "iSortedTextTable.pdf";
		
        File downloadFile = new File(fileRef);

        try {
            FileInputStream inStream = new FileInputStream(downloadFile);
          
	        OutputStream outStream =  httpresponse.getOutputStream();
	         
	        byte[] buffer = new byte[4096];
	        int bytesRead = -1;
	         
	        while ((bytesRead = inStream.read(buffer)) > 0) {
	            outStream.write(buffer, 0, bytesRead);
	        }
	         
	        outStream.flush();
	        inStream.close();
            outStream.close();
        
        } catch(Exception e) {
        	e.printStackTrace();
        }

		return false;
	}

That is a snippet that I hope contains the relevant code.  The code runs without error.   In debug I can see that bytes are being written to the output stream but in the browser, nothing renders.  If I use the console to view the contant of the http response, I see stuff like this:

 %PDF-1.4
%����
2 0 obj
<</Length 544/Filter/FlateDecode>>stream


....and much much more "junk"

So I am not sure what is going on.  It *seems* like the pdf is being sent as a response but there is something wrong the data somehow.  I have searched for possible causes for a few days but I haven't come across a solution.  Is there a setting or config option I need to change?  Seems like I am just missing something simple.

Thanks,

Pete

Jamie Sammons, modified 2 Years ago. New Member Posts: 2 Join Date: 10/16/19 Recent Posts

This might work PortletResponseUtil.sendFile but You might need to clean up the file is this api would generates and stores the pdf in your server.

Thanks, 

Krishna 

thumbnail
Jamie Sammons, modified 2 Years ago. Regular Member Posts: 225 Join Date: 4/7/11 Recent Posts

Thanks Krishna,

I had come across the PortletResponseUtil.sendFile solution early on in my research but it returned the same Response.  Not sure why this particular solution wasn't working.  What I ended up doing was to capture the response on the client and then render it like so after a successful ajax call:

 

        let blob = new Blob([result], {type: 'application/pdf'});
        
        var filename = "Data-Report.pdf";
        
        var element = document.createElement('a');
        
        let objectURL = window.URL.createObjectURL(blob);
        
        element.href = objectURL;
        
        element.target = '_self';
        
        element.download = filename;

        element.style.display = 'none';
        
        document.body.appendChild(element);

        element.click();

        document.body.removeChild(element);
        
        return ;

Not optimal, but it DID work.  Still, I'd love to know why the original approach wasn't working
.
Appreciate the feedback.

Pete