2010-07-07 55 views
3

我在asp.net应用程序(使用IKVM)中将flyingsaucer与iText一起使用将HTML转换为PDF。如果我直接在html中放置一个样式,它可以很好地工作(甚至是样式标签之间的样式),但是当我链接样式表时,它没有注意到它,并生成没有样式的pdf。Flying Saucer not reading stylesheet

为什么会出现这种情况?

这是我使用

 Dim renderer As New ITextRenderer 
     Dim buf As New StringBuffer 
     buf.append(HTML) 
     Dim builder As DocumentBuilder = DocumentBuilderFactory.newInstance.newDocumentBuilder() 
     Dim doc As Document = builder.parse(New StringBufferInputStream(buf.toString)) 

     renderer.setDocument(doc, Nothing) 
     renderer.layout() 

     renderer.createPDF(os) 

的代码,这是链接样式表

<link rel="stylesheet" href="stylemove.css" type="text/css" /> 

回答

2

如果您使用的是https,那么飞碟将无法读取.css文件,直到您使java的密钥库包含Web服务器的证书为止。

我也有同样的问题太多......看到这样的讨论

https://code.google.com/p/jmesa/issues/detail?id=182

如果你解决了任何其他的方式,请让我知道!

谢谢。

+0

将它添加到java默认cacerts修复它。 (--server.ssl.key-store仅适用于tomcat) – lilalinux 2018-03-06 10:06:53

1

简单的解决方案:

如果你想快速测试,看看你的文件将与您的风格下工作(无需编写大量的代码将它集成到你的应用程序)。只需将您需要的CSS复制并粘贴到您的页面中即可。

越是工作方案

我的解决办法是阅读的CSS,并把它转换成html用预处理。由于这是一个较老的应用程序,可能不完全符合xhtml,我使用JSoup来加载html。下面的代码进行预处理。我会说,这些是代码片段,让你开始。伟大的事情,一旦你得到它的工作,你可以将您的服务器上的任何页面转换为PDF格式,无需任何额外的代码。在我的情况下,我设置了一个过滤器来查找特定的参数。如果该参数存在,我用请求包装器包装请求以访问html页面的最终呈现字节。然后我使用Jsoup解析它,然后pre =处理它。

/**this method uses JSOUP Document here is org.jsoup.nodes.Document 
*/ 
@Override 
    public void modifyDOM(MyResourceResolver resources, Document normalizedDOM) { 

     //move style into head section 
     Elements styleTags = normalizedDOM.getElementsByTag("style"); 

     normalizedDOM.select("style").remove(); 

     for (org.jsoup.nodes.Element linkElement : styleTags) { 

      String curHead = normalizedDOM.head().html(); 
      normalizedDOM.head().html(curHead + "\n" + linkElement.html() + "\n"); 


     } 


     //now resolve css 
     Elements links = normalizedDOM.getElementsByTag("link"); 


     for (org.jsoup.nodes.Element linkElement : links) { 

      String linkHref = linkElement.attr("href"); 
      if (linkHref == null) { 
       linkHref = ""; 
      } 


      String mediaSelector = linkElement.attr("media"); 
      if (mediaSelector == null) { 
       mediaSelector = ""; 
      } 
      mediaSelector = mediaSelector.trim(); 
      if ("".equalsIgnoreCase(mediaSelector) || ("print".equalsIgnoreCase(mediaSelector))) { 

       byte[] contents = resources.getContentsOfHref(linkHref); 

       if (null != contents) { 
        //we've got the info let's add to the document as is 
        Tag styleTag = Tag.valueOf("style"); 
        Attributes styleAttributes = new Attributes(); 
        styleAttributes.put("type", "text/css"); 
        String baseUri = ""; 
        org.jsoup.nodes.Element styleElement = new Element(styleTag, baseUri, styleAttributes); 
        styleElement.text(new String(contents)); 
        String curHead = normalizedDOM.head().html(); 
        normalizedDOM.head().html(curHead + "\n<style type='text/css'>" + styleElement.html() + "</style>\n"); 

       } 
      } 


     } 


     normalizedDOM.select("link").remove(); 
     normalizedDOM.select("script").remove(); 
    } 

由于我插入的CSS和飞碟不支持JavaScript,我只是在预处理结束时从文档中删除这些引用。类MyResourceResolver只是我写的一个类,它引用了servlet上下文。实际读取服务器的css字节的方法看起来像这样:

public byte[] getContentsOfHref(String href) { 
     byte[] retval = null; 
     byte[] buf = new byte[8195]; 
     int nread; 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 

     InputStream is = null; 
     try { 

      if (href.startsWith("/myurlcontext")) { 
       href = href.substring("/myurlcontext".length()); 
      } 
       is = context.getResourceAsStream(href); 
       while ((nread = is.read(buf)) >= 0) { 
        bos.write(buf, 0, nread); 
       } 
       retval = bos.toByteArray(); 


     } catch (Exception ex) { 
      //do nothing for now 
     } finally { 
      try { 
       is.close(); 
      } catch (Exception ex) {/*do nothing*/} 
     } 
     if (retval == null) { 
      System.out.println("Did not find: " + href); 
     } else { 
      System.out.println("Found: " + href + " " + retval.length + " bytes"); 
     } 
     return retval; 
    } 

下一个问题,如何初始化JSOUP Dom。嗯,我这样做,在读取所呈现的JSP页面的内容并把它传递给我的PDF生成代码的请求包装:

String renderedJSPString = new String(renderedJSP); 
//these escape sequences are nuisance in xhtml. 
     renderedJSPString = renderedJSPString.replaceAll("&nbsp;|&copy;|&amp;|&lt;|&gt;", ""); 
     org.jsoup.nodes.Document parsedHtmlDOM = Jsoup.parse(renderedJSPString); 
     org.jsoup.nodes.Document normalizedDOM = parsedHtmlDOM.normalise(); 
     normalizedDOM.outputSettings().escapeMode(Entities.EscapeMode.xhtml); 
     normalizedDOM.outputSettings().prettyPrint(true); 
... 
preProcessor.modifyDOM(resolver, normalizedDOM); 
... 
0

你不设置文档的基本URL在您的通话setDocument。正如我发现的,飞碟需要解决CSS和图像链接问题。欲了解更多详情,请参阅this answer

相关问题