0

在首先生成的 iframe 中生成预览页面后,servlet 生成 PDF 文档。这通常有效,看起来像这样:

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if ("directPrintDocumentDoIt".equals(request.getParameter("method")))  {
            generatePDF(request, response);
        }
        if ("directPrintDocumentWaiting".equals(request.getParameter("method")))  {
            String queryString = request.getQueryString().replace("directPrintDocumentWaiting", "directPrintDocumentDoIt");
            renderWaiting(request, response, queryString);
        }
        if ("directPrintDocument".equals(request.getParameter("method")))  {
            String queryString = request.getQueryString().replace("directPrintDocument", "directPrintDocumentWaiting");
            renderIFrameWaiting(request, response, queryString);
        }
    }

首先,调用“directPrintDocument”和方法“renderIFrameWaiting”,生成 iframe 页面并将内容写入 servlet 响应(iframe src 调用 doPost 的下一部分。我确信这不会产生错误,所以我省略了这个代码片段)。然后调用“directPrintDocumentWaiting”和“renderWaiting”方法,在之前生成的 iframe 页面中生成预览页面,而生成的 javascript 调用“directPrintDocumentDoIt”最终生成 PDF:

private void renderWaiting(HttpServletRequest request, HttpServletResponse response, String queryString) throws IOException  {
    StringBuffer output = new StringBuffer();
    response.setContentType("text/html; charset=ISO-8859-1");
    response.setHeader("Cache-Control", "no-cache");
    output.append("<html>\n");
    output.append("<head>\n");
    output.append("<meta http-equiv='Content-Type' content='text/html;charset=iso-8859-1'>\n");
    output.append("<meta http-equiv='expires' content='0'>\n");
    output.append("<meta http-equiv='cache-control' content='no-cache'>\n");
    output.append("<meta http-equiv='pragma' content='no-cache'>\n");
    output.append("</head>\n");
    output.append("<script type=\"text/javascript\">\n");
    output.append("function formSubmit() {\n");
    output.append("document.forms[0].target=\'_self\';\n");
    output.append("document.body.style.cursor = \"wait\";\n");
    output.append("var formAction = document.forms[0].action;\n");
    output.append("document.forms[0].submit();\n");
    output.append("}\n");
    output.append("</script>\n");
    output.append("<body onload=\"self.focus(); formSubmit();\">\n");
    output.append("<form name=\"druckenForm\" method=\"post\" action=\"" + request.getRequestURI() + "?" + queryString + "\" onsubmit=\"return false;\">\n");
    output.append("<p align=\"center\" valign=\"center\">Druck wird erzeugt...\n</p>\n");
    output.append("<p align=\"center\" valign=\"center\">Der erstmalige Start kann etwas l&auml;nger dauern.</p>\n");
    output.append("</form>\n");
    output.append("</body>\n");
    output.append("</html>");
    response.setContentLength(output.length());
    response.getOutputStream().write(output.toString().getBytes());
    response.getOutputStream().flush();
    response.getOutputStream().close();
}

这通常有效,但有时会发生一些奇怪的事情。不知何故,最后一次调用“directPrintDocumentDoIt”将被调用两次,因此 generatePDF 也将被调用两次,整个打印输出陷入困境(在大多数情况下,PDF 将被白页覆盖)。这种情况发生的概率为 50 次中的 1 次,因此几乎无法重现。首先我想到了一些线程问题,所以我在每次调用时记录了线程 ID:

log.info("> current thread:" + Thread.currentThread().getId());

线程 id 总是相同的,所以我怀疑这真的是线程问题。令我困惑的是,当发生此错误时,提琴手在执行 javascript POST 调用后记录了第 4 次调用。通常有 3 次调用(“directPrintDocument”、“directPrintDocumentWaiting”和“directPrintDocumentDoIt”)。当有 4 次调用时,它总是以相同的方式发生:“directPrintDocumentDoIt”将被调用两次(与 POST 请求相同的 URL)但突然作为 GET 请求。我不知道这个 GET 请求来自哪里(在“generatePDF”中没有其他请求调用)。因此,要么是 javascript 产生了一些奇怪的行为(但为什么很少发生),要么是 web 容器(Websphere)产生了一些我不明白的奇怪的东西。有趣的是,提琴手在第 3 次和第 4 次调用时显示了不同的实体大小。正确的 POST 调用的实体大小为 84.138 字节。第 4 次调用(错误的)有 83.883 个字节。我不知道这意味着什么,但也许这些信息会有所帮助。我感觉这个错误在我重新启动或发布到 Websphere 后更频繁地发生。在这种情况下,它会在第一次尝试时发生(但并非总是如此)。这不可能是巧合。有什么想法吗?我感觉这个错误在我重新启动或发布到 Websphere 后更频繁地发生。在这种情况下,它会在第一次尝试时发生(但并非总是如此)。这不可能是巧合。有什么想法吗?我感觉这个错误在我重新启动或发布到 Websphere 后更频繁地发生。在这种情况下,它会在第一次尝试时发生(但并非总是如此)。这不可能是巧合。有什么想法吗?

4

1 回答 1

0

显然错误是由pdfwriter引起的。容易出错的代码如下所示:

        response.reset();
        response.setContentType("application/pdf");
        response.setContentLength(pdfContent.length);
        response.setHeader("Content-Disposition", "inline; filename=RANDOMFILE.pdf");
        response.addHeader("Accept-Ranges", "bytes");
        response.getOutputStream().write(pdfContent);
        response.getOutputStream().flush();
        response.getOutputStream().close(); 

我不知道为什么,但有时这个标头会导致第二个请求。当我将其更改为以下内容时,pdf 生成后我不再得到白页。所以这似乎是解决方案。

response.setContentType("application/pdf");
response.setContentLength(pdfContent.length);
response.getOutputStream().write(pdfContent);
response.getOutputStream().flush();
response.getOutputStream().close(); 
于 2011-09-22T12:57:36.227 回答