首页 文章

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

提问于
浏览
2

当我尝试使用 iText 创建 PDF 文件并希望之后立即下载时,我遇到了问题。首先我使用 iText 库创建一个 PDF 文件,该文件被写入服务器上的 TEMP 文件夹,这一切都正常。但之后我打电话给下载屏幕,将 PDF 文件从 TEMP 文件夹下载到客户端,这里出了点问题。下载屏幕显示 Firefox(浏览器)图标而不是 Acrobat 图标。当我下载文件时,我只能看到空白的 PDF 页面,但页面数量是正确的。 E.g。我有一个 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 回答

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

相关问题