草庐IT

java - 使用 iText,如何使用 CssResolver 和 CssFile 将 css 应用到我的 PDF 文档?

coder 2024-03-07 原文

感谢您的帮助...

问题

在将 html 表格标签/片段(我已将其转换为字符串)转换为 PDF 文档时...

我能够使用这种技术成功将 css 样式应用到 PDF 文档...

CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(false);  
cssResolver.addCss("td {border-right: white .1px solid;}", true);

但是,我不成功使用现有的 css 文件(即使用 CssFile 对象)将 css 应用于 PDF 文档,就像这样...

CSSResolver cssResolver = new StyleAttrCSSResolver();
InputStream csspathtest = Thread.currentThread().getContextClassLoader().getResourceAsStream("styles/itextweb.css");            
CssFile cssfiletest = XMLWorkerHelper.getCSS(csspathtest);
cssResolver.addCss(cssfiletest);             

...我无法使它正常工作,也不知道问题出在哪里...我正在...

Java.io.IOException The document has no pages

问题:

如何正确使用 CssFile 和 CssResolver 将 css 样式(即从现有的“.css”文件)应用到我的 PDF 文档? (我使用 iText 实现此目的的方式有什么问题?)

(再次感谢您对此的任何帮助/指导)

================= 下面是更详细的信息 ===================

Java 6、JSF (Mojarra) 2.1.11、Primefaces v3.4.2、itextpdf v5.3.4、xmlworker v1.2.1

这是有问题的“printPDF”函数...

public void createPDF() throws DocumentException, CssResolverException
{
    FacesContext context = FacesContext.getCurrentInstance();
    ExternalContext econtext = context.getExternalContext();

    try
    {
        String htmlstring   = context.getExternalContext().getRequestParameterMap().get("testForm:htmlstring");

        InputStream is = new ByteArrayInputStream(htmlstring.getBytes());             
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); 

        // step 1
        Document document = new Document();

        // step 2
        PdfWriter writer = PdfWriter.getInstance(document, baos);

        writer.setInitialLeading(12.5f);

        // step 3
        document.open();

        HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);

        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

        // CSS
        CSSResolver cssResolver = new StyleAttrCSSResolver();
        InputStream csspathtest = Thread.currentThread().getContextClassLoader().getResourceAsStream("styles/itextweb.css");            
        CssFile cssfiletest = XMLWorkerHelper.getCSS(csspathtest);
        cssResolver.addCss(cssfiletest);             

        Pipeline<?> pipeline =  new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer)));

        XMLWorker worker = new XMLWorker(pipeline, true);
        XMLParser p = new XMLParser(worker);
        p.parse(is); //new FileInputStream("results/demo2/walden.html"));

        // step     
        document.close();

        //post back...
        HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
        response.setContentType("application/pdf");
        response.setHeader("Expires", "0");
        response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");           
        response.setHeader("Content-Type", "application/pdf");
        response.setHeader("Content-disposition","attachment;filename=file.pdf");
        response.setContentLength(baos.size());
        OutputStream os = response.getOutputStream();
        baos.writeTo(os);
        os.flush();
        os.close();
        context.responseComplete();
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    catch (DocumentException e)
    {
        e.printStackTrace();
    }
}

这是包含要解析为 pdf 的 html 表格片段的页面(即 id="table1")...

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:p="http://primefaces.org/ui">
    <f:view contentType="text/html">
        <h:head>
            <title>test html-to-pdf with itext...</title>
            <meta charset="utf-8" />
        </h:head>
        <h:body>
            <h:form id="testForm">

                <p:panel id="queryPanel"  header="...test itext html-to-pdf conversion..." style="width:100%;">

                    <table id='table1'>
                        <thead class="dt-thd">
                            <tr id="table1-h-hdr-row">
                                <th style="width: 120px" class="dt-hhdr-c " >Last name</th>
                                <th style="width: 120px" class="dt-hhdr-c " >First Name</th>
                                <th style="width: 120px" class="dt-hhdr-c " >Middle Name</th>
                                <th style="width: 180px" class="dt-hhdr-c " >Date Of Birth</th>

                            </tr>
                        </thead>
                        <tbody>
                            <tr class="dt-r-even" onclick="uiOnRowClick('table1', 14, this)">
                                <td style="width: 120px" class="dt-c  row-selected-left" ><a class="column-link " onfocus="uiOnRowClick('table1', 14, this.parentNode.parentNode)" onclick="storeFilters()" href="#">lastnameAAA</a></td>
                                <td style="width: 120px" class="dt-c  row-selected" >firstnameAAA</td>
                                <td style="width: 120px" class="dt-c  row-selected" >A</td>
                                <td style="width: 180px" class="dt-c  row-selected" >11/27/1971</td>
                            </tr>
                            <tr class="dt-r-odd" onclick="uiOnRowClick('table1', 14, this)">
                                <td style="width: 120px" class="dt-c " ><a class="column-link " onfocus="uiOnRowClick('table1', 14, this.parentNode.parentNode)" onclick="storeFilters()" href="#">lastnameBBB</a></td>
                                <td style="width: 120px" class="dt-c " >firstnameBBB</td>
                                <td style="width: 120px" class="dt-c " >B</td>
                                <td style="width: 180px" class="dt-c " >01/15/1951</td>
                            </tr>
                            <tr class="dt-r-even" onclick="uiOnRowClick('table1', 14, this)">
                                <td style="width: 120px" class="dt-c " ><a class="column-link " onfocus="uiOnRowClick('table1', 14, this.parentNode.parentNode)" onclick="storeFilters()" href="#">lastnameCCC</a></td>
                                <td style="width: 120px" class="dt-c " >firstnameCCC</td>
                                <td style="width: 120px" class="dt-c " >C</td>
                                <td style="width: 180px" class="dt-c " >02/16/1962</td>
                            </tr>
                            <tr class="dt-r-odd" onclick="uiOnRowClick('table1', 14, this)">
                                <td style="width: 120px" class="dt-c " ><a class="column-link " onfocus="uiOnRowClick('table1', 14, this.parentNode.parentNode)" onclick="storeFilters()" href="#">lastnameDDD</a></td>
                                <td style="width: 120px" class="dt-c " >firstnameDDD</td>
                                <td style="width: 120px" class="dt-c " >D</td>
                                <td style="width: 180px" class="dt-c " >03/17/1973</td>
                            </tr>
                            <tr class="dt-r-even" onclick="uiOnRowClick('table1', 14, this)">
                                <td style="width: 120px" class="dt-c " ><a class="column-link " onfocus="uiOnRowClick('table1', 14, this.parentNode.parentNode)" onclick="storeFilters()" href="#">lastnameEEE</a></td>
                                <td style="width: 120px" class="dt-c " >firstnameEEE</td>
                                <td style="width: 120px" class="dt-c " >E</td>
                                <td style="width: 180px" class="dt-c " >04/18/1984</td>
                            </tr>
                            <tr class="dt-r-odd" onclick="uiOnRowClick('table1', 14, this)">
                                <td style="width: 120px" class="dt-c " ><a class="column-link " onfocus="uiOnRowClick('table1', 14, this.parentNode.parentNode)" onclick="storeFilters()" href="#">lastnameFFF</a></td>
                                <td style="width: 120px" class="dt-c " >firstnameFFF</td>
                                <td style="width: 120px" class="dt-c " >F</td>
                                <td style="width: 180px" class="dt-c " >05/19/1995</td>
                            </tr>
                        </tbody>
                    </table>

                    <p:commandButton
                        id="printPdf"
                        value="Print"
                        action="#{testBean.createPDF2}"
                        ajax="false"
                        onclick="printPreview(this);this.form.target='_blank'"/>

                    <h:inputHidden id="htmlstring" value="no value"/>

                </p:panel>

            </h:form>

            <h:outputStylesheet  library="styles"    name="itextweb.css"      />
            <h:outputScript      library="primefaces" name="/jquery/jquery.js" />
            <h:outputScript      library="primefaces" name="/jquery/plugins/ui/jquery-ui.custom.js" />
            <h:outputScript      library="primefaces" name="/jquery/plugins/inputmask/maskedinput.js" />
            <h:outputScript      library="js"         name="itextweb.js" />
        </h:body>
    </f:view>
</html>

这里是使用的javascript...

function uiOnRowClick(a, b, c)
{
    alert("uiOnRowClick(a,b,c) function called...blah...");
}

function storeFilters()
{
    alert("storeFilters() function called...bleah...");
}

function printPreview(e)
{
    var t = document.getElementById("table1");
    var htmlstring = "<table id='table1-hdr' class='dt' style='width:2416px;position:absolute'>" + t.innerHTML + "</table>";
    document.getElementById('testForm:htmlstring').value = htmlstring;
}

这是这个例子的 CSS 样式表...

.text1
{
    background-color: transparent !important;
    font-weight: bold;
    font-size: 2em;
    color: blue;
    text-align:center;
}

.ui-inputfield {
    background: white !important;
    height: 10px !important;
    vertical-align: middle;
    display:inline-block;
    white-space: nowrap;
}


.ui-button
{
    margin-top: .5px !important;
    vertical-align: middle !important;
    display:inline-block !important;
    white-space: nowrap !important;
    text-align: center !important;
}

.ui-message-error
{
    background: transparent !important;
    border: none !important;
    font-size: .9em !important;
    font-weight: normal !important;
    font-family: Arial, sans-serif !important;
}

.ui-message-error-icon {
    display: none;
}

.ui-messages-error
{
    background: transparent !important;
    border: none !important;
    font-size: .9em !important;
    font-weight: normal !important;
    font-family: Arial, sans-serif !important;
}

.ui-messages-error-icon {
    display: none;
}

.ui-inputfield.ui-state-error
{
    background: pink !important;
}

form *
{
box-sizing: content-box !important;
-moz-box-sizing: content-box !important;
-ms-box-sizing: content-box !important;
}


.ui-widget, .ui-widget .ui-widget
{
font-size: 90% !important;
}


.dt-thd
{

}

.table1-h-hdr-row
{

}

.dt-hhdr-c
{
    color: blue;
    background-color:  lightgray;
}

.dt-r-odd
{
    background-color: aliceblue;
}

.dt-r-even
{
    background-color:  lightskyblue;
}

.dt-c
{
    font-size: 8px;
    font-weight: normal;
}

下面是用于此示例的 pom.xml(说明依赖项/版本/等)...

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>aaa.bbb.ccc</groupId>
    <artifactId>itextweb-war</artifactId>
    <packaging>war</packaging>
    <version>1</version>
    <name>itextweb-war</name>
    <url>http://maven.apache.org</url>

    <dependencies>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.1.11</version>
        </dependency>

        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.1.11</version>
        </dependency>

        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>el-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>el-impl</artifactId>
            <version>2.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>3.4.2</version>
        </dependency>

        <dependency>
            <groupId>org.primefaces.themes</groupId>
            <artifactId>aristo</artifactId>
            <version>1.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.3.4</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>1.2.1</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
            </plugin>

        </plugins>
        <finalName>${project.name}-${project.version}</finalName>
    </build>
</project>

最佳答案

从您的代码开始创建了一个项目,经过测试,它可以很好地从带有外部 CSS 的 html 文件创建 PDF 文件。

这是公共(public)存储库:https://github.com/valentin-nasta/itext-html-css-pdf-jsf-template .

关于java - 使用 iText,如何使用 CssResolver 和 CssFile 将 css 应用到我的 PDF 文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14783231/

有关java - 使用 iText,如何使用 CssResolver 和 CssFile 将 css 应用到我的 PDF 文档?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

随机推荐