Sunday, May 21, 2006

PDF handling

Read and open the PDF in a new browser window

The goal is to use JSF to open a PDF file inline in a new browser window without showing the full PDF path and filename for some (security) reasons. You can use either a h:commandLink or a h:commandButton for this:

<h:form>
    <h:commandLink value="Download PDF" action="#{myBean.downloadPDF}" target="_blank" />
</h:form>
<h:form target="_blank">
    <h:commandButton value="Download PDF" action="#{myBean.downloadPDF}" />
</h:form>

Note: when using an ajax-capable command button/link from a library such as PrimeFaces, then don't forget to turn off the ajax capability by e.g. adding ajax="false" in case of PrimeFaces command components. It's namely not possible to download files using ajax, for the simple reason that JavaScript is due to security restrictions not capable of forcing a Save As dialogue from the client side on.

The downloadPDF() method of the backing bean MyBean.java sends the PDF to the HttpServletResponse as follows:

package mypackage;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;

public class MyBean {

    // Constants ----------------------------------------------------------------------------------

    private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.

    // Actions ------------------------------------------------------------------------------------

    public void downloadPDF() throws IOException {

        // Prepare.
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

        File file = new File(getFilePath(), getFileName());
        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try {
            // Open file.
            input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);

            // Init servlet response.
            response.reset();
            response.setHeader("Content-Type", "application/pdf");
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setHeader("Content-Disposition", "inline; filename=\"" + getFileName() + "\"");
            output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

            // Write file contents to response.
            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
            int length;
            while ((length = input.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }

            // Finalize task.
            output.flush();
        } finally {
            // Gently close streams.
            close(output);
            close(input);
        }

        // Inform JSF that it doesn't need to handle response.
        // This is very important, otherwise you will get the following exception in the logs:
        // java.lang.IllegalStateException: Cannot forward after response has been committed.
        facesContext.responseComplete();
    }

    // Helpers (can be refactored to public utility class) ----------------------------------------

    private static void close(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException e) {
                // Do your thing with the exception. Print it, log it or mail it. It may be useful to 
                // know that this will generally only be thrown when the client aborted the download.
                e.printStackTrace();
            }
        }
    }

}

The names of the getFilePath() and getFileName() are self-explaining, so there is no need to describe those methods.

If you don't care about showing request parameters or filenames in the URL, then you can also consider to use a FileServlet.

Copyright - There is no copyright on the code. You can copy, change and distribute it freely. Just mentioning this site should be fair.

(C) May 2006, BalusC

86 comments:

Unknown said...

Hi Balu,

Thanks a lot for all your JSF articles. They have all been very useful.

I tried the sample for "PDF handling" and it worked fine by opening the pdf file on the same window as the commandLink.

I tried to implement the jsp file option - where the pdf opens in a new window other than the commandLink window. As soon as I click on the commandLink, it opens a new window and displays the "java null pointer exception" error. I believe I am doing exactly the same code as you given in your sample. Can you please let me know why I am receiving the error?

Thanks
Aish

Bauke Scholtz said...

Some object in your code is null while it is been accessed. This would throw a NPE.

Read the stacktrace in the application server logs, find the root cause and fix it accordingly.

Unknown said...

Hi Baluc,

Just wanted to check with you if you had a chance to see my earlier response. If you get a moment, can you please take a look at the log and let me know why I am getting a JPE?

Thanks a lot
Aish

Kiran0927 said...

Hi Balusc,
I have two blob objects that hold the different pdf files.i want to show these two pdf files as one file using a servlet response.Could you please let meknow how could i do that?
I can show one file from the servlet response.if i try to combine them uisng the inputstream and display ,iam not able to .

Bauke Scholtz said...

Use the iText API to merge PDF files in Java.

Kiran0927 said...

THanks for the previous response.

is there any way i could combine the blobs that contain the pdfs without using the iText API to display them using the servlet response.

Kiran0927 said...

Hi balusc,
As you suggested iam planning to use Itext api for combining the pdfs.

i am reading two blobs from data base as streams into a List Inputstream and returing that list using the stateless EJB to a servlet .My idea is getting that list in the servlet and concatenate them using the itext API to display as one pdf.
But iam getting an exception to read it from the bean.

exception is something like as below..

java.rmi.UnmarshalException: cannot unmarshaling return; nested exception is:
java.io.NotSerializableException: oracle.jdbc.driver.OracleBlobInputStream
at weblogic.rmi.internal.ServerRequest.unmarshalReturn(ServerRequest.java:105)
at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:338)
at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:252)
at com.dteco.bvs.process.DocumentManagerEJB_6gzkd3_EOImpl_922_WLStub.retrieveBill(Unknown Source)
at com.dteco.bvs.RequestProcessor.doPost(RequestProcessor.java:92)
at com.dteco.bvs.RequestProcessor.doGet(RequestProcessor.java:60)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:743)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:283)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3228)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2002)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:1908)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1362)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)


Let meknow if you got any idea about this error...Eventually iwant to use the way it was done in the below url..
http://java-x.blogspot.com/2006/11/merge-pdf-files-with-itext.html

Kiran0927 said...

hi Balusc,
Do you have any code to combine the pdfs that are in the BLOBS and display .
Could you pleas epost it if you have any code..

thanks

Bauke Scholtz said...

Just get the byte array (inputstream) from the BLOB and handle accordingly.

Kiran0927 said...

Hi BAlusc,
I am getting the byte array (input stream) and was able to dispaly it when there is one pdf document.When i have more than one document,iam keeping all those byte arrays in a different list objects .allthose byte arrays iam writing them to an output stram to dispaly as one servlet response.At this point aim seeing an error in dispalying the pdf and could able to see a part of the first document alone.
let me know if you gto any code snippet to combine the byte array strams to dispaly in single servlet response.

thanks

Bauke Scholtz said...

As said, you can use iText to merge PDF files. Just glueing the unchanged byte arrays together is NOT going to work. If you don't want to use 3rd party API's but rather write your own, then learn how PDF files are structured at binary level and write code accordingly.

Kiran0927 said...

Iam okay to user the Itext API .I am just wondering how to concatenate the pdfs using the API when i have the byte array in a list which i got from the blob.All i ahve in my servlet is List cotain different lists and each list contain the pdf files byte arrays.

Do you got any code for this type of list to read from itext apit to combine.

let meknow.
Many thanks for your valuable suggestions

Kiran0927 said...

Balusc,
LEt meknow if you have any idea as iam having issues when i try to use the iText APi .The exception when iam rreading the byte array using iText PdfReader is as below..


java.io.IOException: Unknown encryption type (4)
at com.lowagie.text.pdf.PdfReader.readDecryptedDocObj(Unknown Source)
at com.lowagie.text.pdf.PdfReader.readDocObj(Unknown Source)
at com.lowagie.text.pdf.PdfReader.readPdf(Unknown Source)

Bauke Scholtz said...

Try posting this issue at the iText mailinglist.

Kiran0927 said...

Hi Balusc,
I am bale to concatinate the pdf with the help of iText API.The problem with was due to the standard security handler.iText api giving us the error as the pdf was the secutiry enabled with the password setup .
Anyway,Many thanks for everthing and i am very much happy to found your BLOG to discuss these king of issues with you.

Thanks you so much



Kiran Jallepalli

sidra said...

Hi, I made a button for generating a pdf. When I run it localy its ok, but when I put the application on Tomcat I get the error: java.lang.NoSuchMethodError: org.apache.fop.fonts.FontInfo.fontLookup([Ljava/lang/String;Ljava/lang/String;I)Lorg/apache/fop/fonts/FontTriplet; org.apache.fop.fo.properties.CommonFont.getFontState(CommonFont.java:157)
although I have the library for FOP and the class FontInfo it's there..any ideas?

Thanks in advance

Daniel said...

Hi, first of all tanks for the great post,
My question is might be off the topic, but, I handled the pdf in the same way, and i also used the target="_blank" , but every time i open a pdf a get the new empty window being opened, i tried to close it from the servlet in couple ways, but without any luck, is there any recommended way to close the new window?
from servlet or using js sowmhow?

Sri Bodapati said...

Hi balusC,

I really appreciate your posts on JSF.

I am trying to open a PDF file on clicking a link from my portlet which is on JSF.

But my PDF files are stored on another machine.

I am using the physical path to my file to pen using h:requestLink

But the browser always looks in my local machines path to get the file and hence says file not found.

Can you direct me in the right way in making this work.

Thank you
Sri.

Bauke Scholtz said...

Check the FileServlet link which I posted at the bottom of the article.

Daniel said...

Hi again... couple of weeks ago i posted a question in this thread...
Any cahnce to get a respond?

Thanks ahead...

Unknown said...

Hi, BalusC,
Thank you for your post. But I tried you code solution for opening xml file and it gets opened in a new tab, not in a new window. Do you know any solutions to this issue?

Bauke Scholtz said...

This is a browser configuration. Nothing to do against.

If you actually wanted a popup, use Javascript's window.open() with an URL pointing to some servlet like the FileServlet example.

Tamil said...

Hi Balu,

I tried your code and in the following way.

1. I added a h:commandLink in my page.
2. if i click the commandlink it will generate a PDF report and display the prompt to open or save. i am also able to open or save the PDF. Everything is fine till this point.
3. Now if I go to my JSF page and try to do any other actions (other than PDF commandLink), the corresponding action is called, and immediately after that action was called,it again shows up the save/open prompt again. I could not understand what the problem was. could you please help me to find out the issue?

Unknown said...

I've tried your tutorial with ICEfaces and this does not working.

What can i do?

thanks in advance!!

Bauke Scholtz said...

Elaborating the "not working" part in more detail.

Tamil said...

Hi BalusC,

can you check my post and help me?

"I tried your code and in the following way.

1. I added a h:commandLink in my page.
2. if i click the commandlink it will generate a PDF report and display the prompt to open or save. i am also able to open or save the PDF. Everything is fine till this point.
3. Now if I go to my JSF page and try to do any other actions (other than PDF commandLink), the corresponding action is called, and immediately after that action was called,it again shows up the save/open prompt again. I could not understand what the problem was. could you please help me to find out the issue?"

Bauke Scholtz said...

Sounds like some bug in IceFaces. Have you addressed this behaviour at their forum/mailinglist/issuetracker?

baron5 said...

Hi,

I've tried your solution, but I tried adding the h:commandLink into a h:datatable. This didn't work very well, when clicking the link it didn't even invoke the downloadPDF-method, just loaded the same page in a new window. Then I tried putting the h:commandLink outside the datatable, and it invoked downloadPDF().

I'm trying to present a list over pdf-documents, and give a link to each of them, so I'd really like to access them from from the datatable...

Could you point me in the right direction?

Thanks,
Helge

Bauke Scholtz said...

The data loading logic is apparetly wrong. The datatable value has to be same during the form submit as it was during the initial display (yes, that are 2 requests). Check the 'Using datatables' article.

baron5 said...

Thanks, I was building the list in the backing bean, which obviously is no good idea if using a commandLink/commandButton. Instead I build the list in the BO.

The 'Using datatables' article was very useful.

Anonymous said...

Hi Balu,

Thanks a lot for all your JSF articles. They have all been very useful.
I am developing a application that shows file structure on the page using rich tree.
to download the file I have a context menu ,on clicking it call the action method same as yours.
its working well but when again I click on tree it shows the content of file on the page.how I can stop this.Should I Open a new window to download the file.
pls help me out.

Unknown said...

Hi BalusC,
I am using the code given by U. But I am getting the below exception.

[8/31/09 15:14:10:808 IST] 00000086 ServletWrappe I SRVE0242I: [EBU User ManagementEAR] [/.EBU_User_Management] [/pages/exception.jsp]: Initialization successful.
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R javax.faces.FacesException: #{previousInvoicesAction.downloadPDF}: javax.faces.el.EvaluationException: java.lang.NullPointerException
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:79)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at com.neotel.exception.NeotelExceptionHandler.processAction(NeotelExceptionHandler.java:49)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at javax.faces.component.UICommand.broadcast(UICommand.java:312)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:302)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:419)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:77)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:220)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:91)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at com.ibm.faces.portlet.FacesPortlet.processAction(FacesPortlet.java:189)
[8/31/09 15:14:10:777 IST] 00000086 SystemErr R at com.ibm.ws.portletcontainer.invoker.impl.PortletFilterChainImpl.doFilter(PortletFilterChainImpl.java:77)
[8/31/09 15:14:10:777 IST] 00000086

My code snippetes is:


FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

String fileName = "Important.txt";
File file = new File( "C:\\LotusConfiguration.pdf");
BufferedInputStream input = null;
BufferedOutputStream output = null;

try {
// Open file.
input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);

// Init servlet response.
response.reset();
response.setContentType("application/pdf");
response.setContentLength((int)file.length());
response.setHeader("Content-disposition", "inline; filename=\"" + fileName + "\"");
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

// Write file contents to response.
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
System.out.println("In while loop length: " + length);
output.write(buffer, 0, length);
System.out.println("In while loop length: " + length);
}

// Finalize task.
output.flush();
System.out.println("output flush " );
}
}


please help.

Regards,
Jitendra

Bauke Scholtz said...

Read the bottom of the stacktrace, find the root cause of the NPE and fix the code accordingly.

Bossie said...

Hey there BalusC,

Every time I run into a JSF problem, I end up on your blog. And so far, every time I read your post, thought about it, tried some things and behold, I get it to work.

Thanks a million for your effort mate!

Pieter

rohit.phuge said...

Hi Baluc,

I need a a help regarding panelCollapsible.I want to refresh a panelCollapsible so that the inputText inside it displays the value in backing bean.

Benoit said...

Hi BalusC,

Thanks a lot for your snippets.
It helped a lot in my JSF project.

Benoît

Roszak said...
This comment has been removed by the author.
Roszak said...

BalusC,
I'm generating a pdf using code similar to you posting. I'm trying to open the pdf in a popup using:

h:commandLink action="#{MyBean.generatePdf}" target="#{MyBean.generate}"" title="Pdf" value="Pdf File" styleClass="shortcut_pdf" onclick="popWindow('', 'Generate','350','250','yes');cancelPropagation(event);">



The first time I click on the commandLink the browser creates the popup, goes out to the server to my MyBean.generatePdf method and creates the pdf in the popup. If I don't manually close the popup and click on the link again the main browser gets replicated in the popup.

I followed it in debugger on server and I see the first time it directly goes into my MyBean.generatePdf method but the second click only takes me into the getter for MyBean.generate and just returns the String "Generate".

Another thing I found is that if I try a third click it works correctly as it did the first time. Why wouldn't it see the action correctly the second time in?

ANy help is greatly appreciated.

Thanks,

Richard

Anonymous said...

I'm having same issue as user, "success_21",


1. I added a h:commandLink in my page.
2. if i click the commandlink it will generate a PDF report and display the prompt to open or save. i am also able to open or save the PDF. Everything is fine till this point.
3. Now if I go to my JSF page and try to do any other actions (other than PDF commandLink), the corresponding action is called, and immediately after that action was called,it again shows up the save/open prompt again. I could not understand what the problem was. could you please help me to find out the issue?"


Any ideas? Thanks.

Webmaster said...

I appreciate the information. Java is one of the consistent player from the development industry which has been providing the wider scope for developers to come out with different solutions.

Vaibhav Natekar said...

Hello BalusC,
I am using your code for downloading an excel file. The content-Type I have given is "application/vnd.ms-excel". The code is same as yours.
But it on clicking the link the files is loaded in browser itself as text file.
I have also tried for pdf, and the result is same. the browser is firefox. And in IE-7 even the text is also not shown. I am using myfaces 1.2 implementation for jsf.

karteek said...

Hi,
I am using embed tag in jsf which renders the pdf in web page as below:



I configured the image servlet in web.xml as below


imageServlet
com.kkk.presentation.servlet.ImageServlet
1


imageServlet
/image/*


but the control is not going into the servlet.
when i use the control is going into servlet.i want similar with the tag also
please help

Unknown said...

Hi BalusC
i am using h:commandLink to download file it work file first time then i again click any any other action in my page then again download function in the bean is callig.

Mani said...

Hi BalusC,
Thank you for you post.
I've tried to do this in my JSF application. The browser(IE6) is always displaying the content of the pdf file in text format in the browser instead of opening the file with a pdf plugin.

I'm using your code with almost no changes.

Any ideas ??

Thanks in advance.

Mani

Mani said...

Hi BalusC,
You code is working when I had it in a simple servlet.

BTW I've forgot to mention I'm using Richfaces 3.3.2.

Thanks,

Mani

Mani said...

I think it has to do with a4j:commandButton. I replaced this with h:commnadButton. Now the pdf is displayed in the browser.

Unknown said...

Hello,

Thanks! It works like a charm

Trinh Ngoc Quang said...

Hi BalusC,

Now, i want to export 2 pdf file when i click button.

Could you help me?

Thanks,

QuangTN

Sam said...

Hi BalusC,

All works fine, but the report is generated by some parameters the user enters, and when the validation fails, opens a new window with the same page project.... :/

dont now what to do. I dont wanna use Js :'(

cma3982 said...

Hi..I used the code to open an excel sheet from jsf application and it worked fine. However I have another button the page that is used to do something else. When i view the excel file on this page and click on the hoer button the page doesn't get submitted for the first time. It gets submitted when i Click it again.

If I remove the part of code for opening the excel sheet from the action method of the first button everything works fine. Can you please explain why opening an excel sheet breaks the second button for the first time.

Alex said...

PDF files may be restored thanks to pdf fixer. It owns high end, easy to use interface for any experienced user. The program is able to work under any Windows OS. The software can't change original info during recovery.

Diepsh said...

Thanks a lot for this article.

Unknown said...

BalusC, you're a lifesaver - faces.responseComplete() was the piece I was missing.

Sangeetha said...

Hi, Wanna to ask u sumthing abt generating a PDF file from a JSF Data table.
I have Data table in my JSF page. Want to generate a PDF file. Is it the same as generating a PDF view from a normal JSF page? Thanks.
Preethi

Sangeetha said...

Hi, Wanna to ask u sumthing abt generating a PDF file from a JSF Data table.
I have Data table in my JSF page. Want to generate a PDF file. Is it the same as generating a PDF view from a normal JSF page? Thanks.
Preethi

Rafael A P Nascimento said...

Hi, BalusC,

I tried your sample and it worked fine.

However, I'd like to only open the pdf file in a new tab, and not downloading it to client. Is it possible ?

Unknown said...

Dear Balu,

I'd like to thank you for your useful articles.
how can I retrieve the pdf file from a database blob

iam said...

i have used same code as above but i am not able to open pdf file.if i used below code pdf file is opened into same window.........

public void viewReport(){
try {
FacesContext.getCurrentInstance()
.getExternalContext().redirect("dds-help.pdf?type=sb");
return;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

i want to open pdf file into new tab please help me i don't why your code is not working on my machine

Unknown said...
This comment has been removed by the author.
oooss said...

Hi BalusC i tried your code in the browser of eclipse the pdf file is opened correctly but moving to firefox or google chrome a pop up windows is displayed to save or open the pdf where the pdf is not opened neither in new windows nor in a new window am i missing something!!

Bauke Scholtz said...

Make sure that you're not invoking the action method by ajax. It's not possible to download files by ajax.

oooss said...

am i using an iframe not a command button since i want to display the pdf in an iframe so i dont have a component which has ajax my code is calling downloadPdf in a PostConstruct method and the iframe is taking the file name as src

iframe src="myPdf.pdf"

where myPdf.pdf is a file in desktop derectory

primeFaceUser said...

Hello BalusC i tried your code and its interesting
Its fine in a dynamic web project
but when moving to a portlet application i am facing a null pointer exception in responce.getOutputStream() where i rediefined in your code by changing
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

to

PortletResponse portalResponse = (PortletResponse) externalContext.getResponse();
HttpServletResponse response = PortalUtil.getHttpServletResponse(portalResponse);

Shivaraj said...

Hi BalusC,
I getting NullPointerException at
output.write(bytes)
I am not getting why output is null
output = response.getOutputStream();

Michael Rojas said...

Hi Balusc,

This article has been really helpful, thanks a lot!!!



Unknown said...

This xmas gonna toast in your name! Thank you for this post and for all java and primefaces content in stackoverflow, you really made my life less painful!

Cheers and Props from Brazil!
Happy holydays.

maartenbay said...

Hi Bauke,

I keep stumbling upon your blogs for a while now, always clear and well explained info which helps me lot in dev life! A big thumbs up there! However this one didn't do it for me =( Don't know why, there is just nothing happening, no useful log entries, nada.
I managed to fix it though by combining your fileservlet blog with a simple prettyfaces mapping. Overkill? Probably. Maybe I blog about it one day myself =)
Cheers from the Netherlands!

Amr Esh said...

Hi Balu.
Thanks for the article. It worked well for me in IE, Chrome n firefox.
Is there a way where i can do the same for ipad, tables and smart phone. I failed using the same method for samsung tablets

Hasan said...
This comment has been removed by the author.
shamu said...

Hi Balu , this code helped me alot.
I am putting bytearray in iframe and opening the editable pdf in the browser . now I want to read the editable pdf content fro the browser in jsf . Can you suggest how can this be achieved.

Thanks in advance...

Unknown said...

Hey Bauke Your tutorials are really of great help. I need help in converting xhtml page to pdf. Can you guide on those lines with some reference.

Ruben said...

Wow! It worked really well! It allows to save the file as PDF (File/save as...) as I wanted. Once more thank you to the JSF master, have a nice day!

Ruben said...

Wow! It worked really well! It allows to save the file as PDF (File/save as...) as I wanted. Once more thank you to the JSF master, have a nice day!

Ruben said...

Wow! It worked really well! It allows to save the file as PDF (File/save as...) as I wanted. Once more thank you to the JSF master, have a nice day!

Ruben said...

Wow! It worked really well! It allows to save the file as PDF (File/save as...) as I wanted. Once more thank you to the JSF master, have a nice day!

Ruben said...

Wow! It worked really well! It allows to save the file as PDF (File/save as...) as I wanted. Once more thank you to the JSF master, have a nice day!

Meu Amigo Normal said...

Thank's Balusc, you save me!!!

Unknown said...

it works .. but ? I have the h:form component in a main template and I use primefaces p:commandButton so we must use ajax="false". We can use js to set form target on _blank using onclick but onComplete doesn't work to reset target to default. can you hel me?

M Chisty said...

Nice example. Working properly. Only one issue: assuming that there is no error and PDF is displayed in a window. However say, when there is an error occurred while displaying a PDF (e.g. statusMessages is not empty) and I want to display the error validation message in the page instead of displaying the PDF. How to achieve this?

[We cannot use ajax due to technology limitation/security reasons]

Any advice?

Thanks.
M.

Unknown said...

Hey Balu,

My iText PDF has links in it but when I click on these links in an iPad, they don't open in a window. How can I correct this?

Thanks for you time.
Priyank

Unknown said...

Hi Balu, everything works but some how mu downloaded xml file has xhtm page source attached at the end. If u have any idea why this might occur please let me know...

Frances said...

This is great info and it works, but I want to pass the filename in the header so the user can then save the pdf with that name. How do I accomplish that?

Thank you,
Frances

Unknown said...

Hi, thanks for your code. It's works perfectly but I would like generate PDF by a bean. Is it possibile?
I use Primefaces 5. User save some data clicking a botton in my jsf page; this botton has an action to call a bean method (I set ajax=false). Within this method I try to insert your "DownloadPDF" call but doesn't work. I would like views my pdf in a new window browser or view a popup to download pdf. Thanks.

Unknown said...

hi, I change your method for work with pdfStamper, i proved the same but it don't work i don't have any warning or error but my pdf don't see in my browser. can you help me??
this is my code
public void crearPdf() throws ServletException, IOException, DocumentException{
System.out.print("Este es el ingreso al metodo crear PDF");
Calendar c = Calendar.getInstance();
String annio=Integer.toString(c.get(Calendar.YEAR));
String day=Integer.toString(c.get(Calendar.DAY_OF_MONTH));
String month=Integer.toString(c.get(Calendar.MONTH));

// Load existing PDF
FacesContext context = FacesContext.getCurrentInstance();
PdfReader reader = new PdfReader("/home/pao/Desktop/plantillaRequisicion.pdf");
// PdfImportedPage page = writer.getImportedPage(reader, 1);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PdfStamper stamp = new PdfStamper(reader, out);
AcroFields form = stamp.getAcroFields();

form.setField("codRequisicion", "JT-"+getCodigoRequisicion()+"-"+annio);
form.setField("fechaReq", day+"-"+month+"-"+annio);
form.setField("Descripcion", req.getDescripcion());


for(int i=0;i<listaMaterialRequisicion().size();i++){

String aux=String.valueOf(listaMaterialRequisicion().get(i).getMaterial().getCodigo());
String aux1=listaMaterialRequisicion().get(i).getMaterial().getDescripcion();
String aux2=listaMaterialRequisicion().get(i).getMaterial().getUnidad();
String aux3=String.valueOf(listaMaterialRequisicion().get(i).getCantidadDeseada());
System.out.println(aux+aux1+aux2+aux3);
int j=i+1;

form.setField("cod"+j, aux);
form.setField("des"+j, aux1);
form.setField("un"+j, aux2);
form.setField("can"+j, aux3);

form.setField("nomApe",listaMaterialRequisicion().get(i).getRequisicion().getEmpleado().getNombre()
+" "+listaMaterialRequisicion().get(i).getRequisicion().getEmpleado().getApellido());
form.setField("cargoCod", listaMaterialRequisicion().get(i).getRequisicion().getEmpleado().getCargo());
}
stamp.setFormFlattening(true);
stamp.close();
reader.close();


writePDFToResponse(context.getExternalContext(), out, "requisicion");
context.responseComplete();

if(context.getResponseComplete()==true){
System.out.print("proceso completado");
}
}


private void writePDFToResponse(ExternalContext externalContext, ByteArrayOutputStream baos, String fileName) {
try {
externalContext.responseReset();
externalContext.setResponseContentType("application/pdf");
externalContext.setResponseHeader("Expires", "0");
externalContext.setResponseHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
externalContext.setResponseHeader("Pragma", "public");
externalContext.setResponseHeader("Content-disposition", "inline; filename=" + fileName + ".pdf");
externalContext.setResponseContentLength(baos.size());
OutputStream out = (OutputStream) externalContext.getResponseOutputStream();
baos.writeTo(out);
externalContext.responseFlushBuffer();
} catch (Exception e) {
//e.printStackTrace();
}

Unknown said...

Great work and very helpful as always. Thanks BalusC!

PDF-download was working fine on Edge, Chrome and FF but I had a problem in InternetExplorer 11: PDF-Plugin cancelled with "No access".

The most simple sollution I could find was to hint, that the PDF should be downloaded rather than inline-edit:

response.setHeader("Content-Disposition", "attachment; filename=...

spyros said...

hI, I create a jsf form from a xhtml file named 1ndex333.xhtml with intellij
the story goes ;
1.The user fills the form
2.my goal is to export this filled form to pdf
questions
a.how can i access this form ?
b.how can i create a pdf file from my url: http://localhost:8080/index333+jsessionid
c.i used your code at
https://stackoverflow.com/questions/5662455/jsf-2-0-convert-xhtml-page-to-pdf-using-flying-saucer-java-lang-illegalstateexc
i do not understand the code below
response.setHeader("Content-Disposition", "inline; filename=\"" + PDF_FILE_NAME + "\"");
OutputStream browserStream = response.getOutputStream();
renderer.createPDF(browserStream);
It does not work for me anyway.
no pdf created .
my index333.xhtml satrts like this

...................
can u help me please?
Spyros