创建和下载PDF文件时的空白页(iText& JSF)

时间:2011-05-07 09:03:23

标签: jsf pdf jsf-2 itext

当我尝试使用iText创建PDF文件并希望之后立即下载时,我遇到了问题。首先我使用iText库创建一个PDF文件,该文件被写入服务器上的TEMP文件夹,这一切都正常。但之后我打电话给下载屏幕,将PDF文件从TEMP文件夹下载到客户端,这里出了点问题。下载屏幕显示Firefox(浏览器)图标而不是Acrobat图标。当我下载文件时,我只能看到空白的PDF页面,但页面数量是正确的。例如。我有一个4页的PDF文件,因此我得到4个空白页,没有内容。但TEMP文件夹中的PDF文件是正确的,它有4页,内容正确。

这是我的java代码,它在用户单击h:commandLink

时执行
     public <E> String createPDF(E type, boolean print) throws Exception {

            Document document = new Document();
// create a File name for the document
            getPdfNaam(type);
            try {
//create a PDF writer
                PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(TEMP + naam + ".pdf"));
//open the PDF document
                document.open();
            } catch (Exception e) {
                e.printStackTrace();
            }
    //build the PDF file using iText
            buildPDFContent(document, type);
    //close the PDF document
            close(document);

            String downloadFile = TEMP + naam + ".pdf";
    //call Servlet for download screen in the browser
                ServletContext context = (ServletContext) ContextProvider.getFacesContext().getExternalContext().getContext();
                HttpServletResponse response = (HttpServletResponse) ContextProvider.getFacesContext().getExternalContext().getResponse();
                response.setContentType("application/force-download");
                downloadFile = TEMP + naam + ".pdf";
                byte[] buf = new byte[1024];
                try {
                    File file = new File(downloadFile);
                    long length = file.length();
                    BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
                    ServletOutputStream out = response.getOutputStream();
                    response.setContentLength((int) length);
                    while ((in != null) && ((length = in.read(buf)) != -1)) {
                        out.write(buf, 0, (int) length);
                    }
                    in.close();
                    out.close();
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
                response.addHeader("Content-Disposition", "attachment; filename=\"" + naam + ".pdf" + "\"");

            return null;

        }

我找到了在此网站上调用下载屏幕的代码http://www.winstonprakash.com/articles/jsf/file_download_link.htm 我搜索了Google和Stack Overflow,但我找不到任何相关问题。我正在使用JSF 2.0任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:3)

内容类型应设置为application/pdf,并且在将任何字节写入响应之前应设置内容处置标头,否则设置它为时已晚。另外,您还可以立即将PDF写入响应的输出流。

总而言之,该方法可以简化如下:

public <E> String createPDF(E type, boolean print) throws Exception {
    getPdfNaam(type); // ??? It should *return* name, not change/set the local value.

    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.setResponseHeader("Content-Type", "application/pdf");
    ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + naam + ".pdf" + "\"");

    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, ec.getResponseOutputStream());
    document.open();
    buildPDFContent(document, type);
    close(document);
}

同时确保您正在调用FacesContext#responseComplete()向JSF发出信号,告知您已经掌握了响应处理,以便它知道它不需要导航到某个视图。

FacesContext.getCurrentInstance().responseComplete();

答案 1 :(得分:0)

你可以让输出流立即响应。以下是我的代码:

        OutputStream out = response.getOutputStream();
        response.setContentType("application/x-msdownload;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;"+"filename="+System.currentTimeMillis()+".pdf");

        Document document = new Document(PageSize.A4, 10, 10, 10,10);
        PdfWriter.getInstance(document, out);
        document.open();
            //The below is document add data
            //....
            //close flow
            if(document!=null){
                document.close();
            }           
            if(out!=null){              
                out.flush();
                out.close();    
            }