2011-09-19 54 views
0

servlet在首先生成的iframe中生成預覽頁面後生成PDF文檔。這通常工作,看起來像這樣: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」被調用而生成的JavaScript調用「directPrintDocumentDoIt」,它最終生成PDF生成以前生成的iframe頁面內預覽頁面:

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倍,所以它幾乎無法再現。首先我想到了一些線索問題,所以我記錄的線程ID在每次調用:

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

線程ID始終是相同的,所以我懷疑這真是一個線程問題。讓我感到困惑的是,當這個錯誤發生時,fiddler在執行javascript POST調用之後記錄第4次調用。通常有3個調用(「directPrintDocument」,「directPrintDocumentWaiting」和「directPrintDocumentDoIt」)。當有4個調用時,它總是以相同的方式發生:「directPrintDocumentDoIt」將被調用兩次(與POST請求相同的URL),但作爲一個GET請求突然被調用。我不知道這個GET請求來自哪裏(在「generatePDF」中沒有其他請求調用)。所以無論是JavaScript產生一些奇怪的行爲(但爲什麼然後很少)或Web容器(Websphere)使我不明白的一些奇怪的事情。有趣的是,提琴手在第3次和第4次調用時顯示不同的實體大小。正確的POST調用的實體大小爲84.138字節。第四次調用(錯誤的)有83.883字節。我不知道這是什麼意思,但也許這個信息是有幫助的。我有這樣的感覺,即在我重新啓動或發佈到Websphere後,這種錯誤經常發生。在這種情況下,它發生在第一次嘗試(但並非總是)。這不可能是巧合。任何想法發生了什麼?

+0

'renderWaiting'看起來不像它爲我生成預覽。它會生成一個自動提交表單。爲什麼需要這一步驟?爲什麼初始操作不能渲染指向PDF渲染操作的iframe? –

+0

「p align」的2行生成「預覽」。在自動提交被調用之後,直到生成pdf需要幾秒鐘的時間。在這個時候,只要PDF尚未生成,客戶端就會看到該頁面。這就是爲什麼這一步很重要。否則這不會以這種方式工作。 – Bevor

+0

如果您直接點擊PDF URL,會發生什麼情況。你有雙重要求嗎?另外,您在HTTP標頭和''標籤中使用ISO8859-1,但使用'getBytes()',不保證使用該編碼。使用'getBytes(「ISO-8859-1」)'。 –

回答

0

顯然,錯誤是由pdfwriter造成的。 errorprone代碼看起來像這樣:

 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(); 
相關問題