2010-07-07 4 views
3

J'utilise flyingsaucer avec iText dans une application asp.net (en utilisant IKVM) pour convertir du HTML en PDF. Si je mets un style directement dans le HTML, cela fonctionne très bien (même les styles mis entre les balises de style), mais quand je lier une feuille de style, il ne parvient pas à le remarquer et produit le pdf sans les styles.Soucoupe volante ne lit pas la feuille de style

Une raison pour laquelle cela se produit?

C'est le code que j'utilise

 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) 

, ce qui est lien vers la feuille de style

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

Répondre

2

Si vous utilisez https, la soucoupe volante ne lira pas les fichiers .css tant que vous n'aurez pas inclus le fichier de clés java dans le certificat de votre serveur Web.

J'ai le même problème aussi ... voir cette discussion

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

Si vous l'avez résolu d'une autre manière, s'il vous plaît laissez-moi savoir !!!

Merci.

+0

En l'ajoutant _also_ aux cacerts java default, il a été corrigé. (--server.ssl.key-store est seulement pour tomcat) – lilalinux

1

Solution facile:

Si vous voulez un test rapide pour voir si votre document travaillera avec vos styles (sans écrire beaucoup de code pour l'intégrer dans votre application). Il suffit de copier et coller le CSS dont vous avez besoin dans votre page.

Plus travail Solution

Ma solution a été de lire le CSS et le mettre en html avec un préprocesseur. Comme il s'agissait d'une application plus ancienne qui n'était peut-être pas entièrement compatible xhtml, j'ai utilisé JSoup pour charger le code HTML. Le code ci-dessous fait le pré-traitement. Je dirai que ce sont des extraits de code pour vous aider à démarrer. La bonne chose, une fois que vous l'avez fait fonctionner, c'est que vous pouvez transformer n'importe quelle page sur votre serveur en PDF sans code supplémentaire. Dans ma situation, je configure un filtre pour rechercher un paramètre spécifique. Si ce paramètre est présent, j'enveloppe la requête avec un wrapper de demande pour accéder aux octets restitués finaux de la page html. J'utilise ensuite Jsoup pour l'analyser, puis pre = le traiter.

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

Depuis que je suis l'insertion de la soucoupe volante css et ne supporte pas javascript, je supprimer simplement les références du document à la fin du pré traitement. la classe MyResourceResolver est juste une classe I qui a écrit une référence au contexte de servlet. la méthode qui lit réellement les octets du hors css du serveur ressemble à ceci:

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; 
    } 

La question suivante, comment initialiser JSOUP Dom.Eh bien, je le fais dans un emballage de demande qui lit le contenu de la page JSP rendu et passe à mon code de production 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

Vous ne définissez pas l'URL de base de votre document dans votre appel setDocument. Flying Saucer a besoin de cela pour résoudre les liens CSS et image, comme je l'ai découvert. Pour plus de détails, voir this answer.

Questions connexes