【问题标题】:Blank pages when creating and downloading a PDF file (iText & JSF)创建和下载 PDF 文件时出现空白页(iText 和 JSF)
【发布时间】:2011-08-20 16:16:04
【问题描述】:

我在尝试使用 iText 创建 PDF 文件并想在之后立即下载时遇到问题。首先,我使用 iText 库创建了一个 PDF 文件,该文件被写入服务器上的 TEMP 文件夹,一切正常。但之后我调用了一个下载屏幕,将 TEMP 文件夹中的 PDF 文件下载到客户端,这里出现了问题。下载屏幕显示 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 任何帮助将不胜感激!

【问题讨论】:

    标签: jsf pdf jsf-2 itext


    【解决方案1】:

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

    all with all,方法可以简化如下:

    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();
    

    【讨论】:

    • 编译器指示它无法“找到”该方法。 setResponseHeader(String, String) 已经感谢您提供有关输出流的提示,更不用说代码了。 :)
    • 那么您实际上没有使用问题中指出的 JSF 2.0。它是在 JSF 2.0 中引入的。另见download.oracle.com/javaee/6/api/javax/faces/context/…
    • 嗯,你是对的,尽管我在 netbeans 中的项目属性表明我正在使用 JSF 2.0 库。我会检查一下并及时通知您。
    • 删除任何 JSF 1.x JAR 文件并确保您的 faces-config.xml 根声明符合 JSF 2.0。
    • 我的项目是一个 Maven 项目。这就是我在 JSF 的 pom.xml 中的内容: com.sun.facesmojarra-jsf-api2.0.0-b04版本> 提供com.sun.facesmojarra-jsf-impl2.0.0-b04 provided 有什么遗漏/错误吗?
    【解决方案2】:

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

            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();    
                }
    

    【讨论】:

      猜你喜欢
      • 2015-03-07
      • 2019-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-23
      • 2011-03-15
      相关资源
      最近更新 更多