2013-01-18 1 views
3

xhtml에서 생성 된 pdf를 처리하기 위해 flyingsaucer을 사용하려하지만 서블릿 예제를 실행하는 데 문제가 있습니다.xhtml에서 flyingsaucer로 PDF 서블릿

다른 모든 flyingsaucer 예제는 나에게 잘 작동하지만 웹app에 통합하기 위해 서블릿으로 작동해야합니다.

import java.io.*; 
import java.net.*; 

import javax.servlet.*; 
import javax.servlet.http.*; 
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import org.w3c.dom.Document; 
import org.xhtmlrenderer.pdf.ITextRenderer; 

public class PDFServlet extends HttpServlet { 

    protected void processRequest(HttpServletRequest request, 
     HttpServletResponse response) throws ServletException, IOException { 
     response.setContentType("application/pdf"); 

     StringBuffer buf = new StringBuffer(); 
     buf.append("<html>"); 

     String css = getServletContext().getRealPath("/PDFservlet.css"); 
     System.out.println("css url 2= " + css); 
     // put in some style 
     buf.append("<head><link rel='stylesheet' type='text/css' "+ 
       "href='"+css+"' media='print'/></head>"); 

     buf.append("<body>"); 
     buf.append("<h1>Quarterly Reports for " + 
      request.getParameter("username")+"</h1>"); 

     buf.append("<table cellspacing='0'>"); 
     buf.append("<tr><th>Sales</th><th>Profit</th><th>Bonus</th></tr>"); 

     // generate sales data 
     int totalSales = 0; 
     int totalProfit = 0; 
     int totalBonus = 0; 
     for(int i=0; i<10; i++) { 
      int currentSales = (int)(Math.random()*10000); 
      int currentProfit = (int)(currentSales*0.2); 
      int currentBonus = (int)(currentProfit*0.33); 
      buf.append("<tr><td>"+currentSales+"$</td><td>"+ 
       currentProfit+"$</td><td>"+currentBonus+"$</td></tr>"); 
      totalSales += currentSales; 
      totalProfit += currentProfit; 
      totalBonus += currentBonus; 
     } 

     buf.append("<tr class='total-header'><td colspan='3'>totals</td></tr>"); 
     buf.append("<tr class='total'><td>"+totalSales+"$</td><td>"+ 
      totalProfit+"$</td><td>"+totalBonus+"$</td></tr>"); 
     buf.append("</table>"); 

     buf.append("</body>"); 
     buf.append("</html>"); 

     byte[] byteArray = buf.toString().getBytes("ISO-8859-1"); 

     // parse our markup into an xml Document 
     DocumentBuilder builder; 
     try { 
      builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
      ByteArrayInputStream baos = new ByteArrayInputStream(byteArray); 
      Document doc = builder.parse(baos); 

      ITextRenderer renderer = new ITextRenderer(); 
      renderer.setDocument(doc, null); 

      OutputStream os = response.getOutputStream(); 
      renderer.layout(); 
      renderer.createPDF(os); 
      os.flush(); 
      os.close(); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

    protected void doGet(HttpServletRequest request, 
     HttpServletResponse response) throws ServletException, IOException { 
     processRequest(request, response); 
    } 

    protected void doPost(HttpServletRequest request, 
     HttpServletResponse response) throws ServletException, IOException { 
     processRequest(request, response); 
    } 

    public String getServletInfo() { 
     return "Short description"; 
    } 
} 

내가이 예외를 얻을 : 다음과 같이

서블릿의 전체 코드는

Jan 17, 2013 7:55:23 PM org.xhtmlrenderer.util.XRLog log 
WARNING: Unhandled exception. IOException on parsing style seet from a Reader; don't know the URI. 
java.io.IOException: Stream closed 
    at java.io.BufferedInputStream.getInIfOpen(Unknown Source) 
    at java.io.BufferedInputStream.read1(Unknown Source) 
    at java.io.BufferedInputStream.read(Unknown Source) 
    at sun.nio.cs.StreamDecoder.readBytes(Unknown Source) 
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source) 
    at sun.nio.cs.StreamDecoder.read(Unknown Source) 
    at java.io.InputStreamReader.read(Unknown Source) 
    at org.xhtmlrenderer.css.parser.Lexer.zzRefill(Lexer.java:1527) 
    ... 
    at org.xhtmlrenderer.context.StyleReference.readAndParseAll(StyleReference.java:122) 
    at org.xhtmlrenderer.context.StyleReference.setDocumentContext(StyleReference.java:106) 
    at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:130) 
    at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:106) 
    at PDFServlet.processRequest(PDFServlet.java:73) 
    at PDFServlet.doGet(PDFServlet.java:75) 
    ... 

그것은 (은 try-catch 블록에서)이 선을 넘어 실행되지 않습니다 :

입력 스트림 유형을 변경하고 xhtml이 정상적으로 실행되었음을 확인하는 등 몇 가지 시도를했지만 그게 n이었습니다. 아무 것도 해결하지 마라.

자바 서블릿에 익숙하지 않아 올바른 문제를 해결할 수 있을지 모르겠다. 실행하기 전에 입력 스트림이 닫히지 않도록하는 방법이 필요하다.

renderer.setDocument(doc, null); 

이 작업이 가능합니까 아니면 다른 작업을해야합니까?

Tomcat 7과 Java 6을 사용하고 있습니다. 다른 사람들이 similar problem을 가졌음을 알았지 만, 서블릿 예제를 실행할 때만 가져옵니다. 다른 모든 예제는 정상적으로 실행됩니다.

+0

추가 시도 후 나는 그것이 생성 된 XML 문서의 CSS 링크에서 CSS를 읽기에 문제가 있음을 발견했다. XML 문서를 만들기 전에 CSS를 링크에서 직접 구문 분석하고 StringBuffer에 포함하면 모든 것이 잘 작동합니다. 어쨌든이 사용 사례를 위해이 작업을 수행해야하지만 직접 문제를 해결하지 않아도되므로 여기서 질문을 남깁니다. – Geronimo

답변

4
String css = getServletContext().getRealPath("/PDFservlet.css"); 

이것은 올바르지 않습니다. 로컬 디스크 파일 시스템 경로가 아닌 URL이어야합니다. IText는 웹 브라우저처럼 "일반적인 방법"으로 URL을 다운로드하려고합니다. 이 될 것이라고 적절한 URL을 구성하는 방법

하나 :

StringBuffer url = req.getRequestURL(); 
String base = url.substring(0, url.length() - req.getRequestURI().length() + req.getContextPath().length()); 
String css = base + "/PDFservlet.css";