`
downpour
  • 浏览: 716100 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
00a07ae5-264f-3774-8903-8ad88ce08cb0
Struts2技术内幕
浏览量:117508
4d8508f2-c0dd-3df8-9483-04cc612afbbc
SpringMVC深度探险...
浏览量:230425
社区版块
存档分类
最新评论

介绍一个PDF的生成方案

    博客分类:
  • Java
阅读更多
在Java世界,要想生成PDF,方案不少。最近一直在和这个东西打交道,所以简单做一个小结吧。

在此之前,先来勾画一下我心中比较理想的一个解决方案。在企业应用中,碰到的比较多的PDF的需求,可能是针对某个比较典型的具备文档特性的内容,导出成为PDF进行存档。由于我们现在往往使用一些开源框架,诸如ssh来构建我们的应用,所以我们相对熟悉的方案是针对具体的业务逻辑设计实体,使用开源框架来实现我们的业务逻辑。而PDF的导出,最好不要破坏现有的程序框架,甚至能复用我们业务逻辑层的代码。因为如果把PDF作为一种特殊的表现形式的话,实际上它有点类似模板。最佳的情况,是我们能够通过编写某种模板,把PDF的大概样子确定下来,然后把数据和模板做一次整合,得到最后的结果

带着这个目标,开始在网上搜索解决方案。也找到了一些方案,下面简单小结一下:

Jasper Report

看到的市面上采用的最多的方案,是Jasper Report。相关的文档也很多,不过很杂,需要完全掌握,我认为还是有些坡度和时间的。这个时间和坡度我认为主要来自于对iReport这个IDE的反复尝试,对里面的每个属性的摸索。

Jasper Report的设计思路,本身是不违反我上面所说的初衷的。因为我们的努力方向是先生成模板,然后得到数据,最后将两者整合得到结果。但是Jasper Report的问题在于,其生成模板的方式过于复杂,即使有IDE的帮助,我们还是需要对其中的众多规则有所了解才行,否则就会给调试带来极大的麻烦。

所以,我认为Jasper Report是一个半调子方案,这种强依赖于IDE进行可视化编辑的方式令我很不爽。同时,由此带来的诸多的限制,相信也让很多使用者颇为头疼。在经历了一番痛苦的挣扎后,决定放弃使用这种方案。

iText

其实Jasper Report是基于iText的。于是有的人会说,那么直接使用iText不是一种倒退么?的确,直接使用iText似乎就需要直接使用原生的API进行编程了。不过幸好iText其实提供了一些方便的API,通过使用这些API,我们可以直接将HTML代码转化成iText可识别的Document对象,从而导出PDF文档。

import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.ArrayList;

import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.html.simpleparser.HTMLWorker;
import com.lowagie.text.html.simpleparser.StyleSheet;
import com.lowagie.text.pdf.PdfWriter;

public class MainClass {
  public static void main(String[] args) throws Exception {
    Document document = new Document();
    StyleSheet st = new StyleSheet();
    st.loadTagStyle("body", "leading", "16,0");
    PdfWriter.getInstance(document, new FileOutputStream("html2.pdf"));
    document.open();
    ArrayList p = HTMLWorker.parseToList(new FileReader("example.html"), st);
    for (int k = 0; k < p.size(); ++k)
      document.add((Element) p.get(k));
    document.close();
  }
}


这是从网上找到的一个例子。从代码中,我们可以看到,iText本身提供了一个简单的HTML的解析器,它可以把HTML转化成我们需要的PDF的document。

有了这个东西,基本上我的目标就能达成一大半了。接下来我的任务就是根据实际情况去编写HTML代码,然后扔进这个方法,就OK了。而真正的HTML代码,我们则可以在这里使用真正的模板技术,Freemarker或者Velocity去生成我们所需要的内容。当然,这已经是我们熟门熟路的东西了。

正当我觉得这个方案基本能符合我的要求的时候,我也同样找到了它的很多弱项:

1. 无法识别很多HTML的tag和attribute(应该是iText的HTMLParser不够强大)
2. 无法识别CSS

如果说第一点我还可以勉强接受的话,那么第二点我就完全不能接受了。无法识别简单的CSS,就意味着HTML失去了最基本的活力,也无法根据实际要求调整样式。

所以这种方案也必然无法成为我的方案。

flying sauser

在这种情况下,我几乎已经燃起了自己编写一个支持CSS解析的HTML Parser的想法。幸好,在一个非常偶然的情况下,我在google中搜到了这样一个开源项目,它能够满足我的一切需求。这就是flying sauser,项目主页是:https://xhtmlrenderer.dev.java.net/

项目的首页非常吸引人:An XML/XHTML/CSS 2.1 Renderer。这不正是我要的东西么?

仔细再看里面的文档:

引用
Flying Saucer is an XML/CSS renderer, which means it takes XML files as input, applies formatting and styling using CSS, and generates a rendered representation of that XML as output. The output may go to the screen (in a GUI), to an image, or to a PDF file. Because we believe most people will be interested in re-using their knowledge of web layout, our main target for content is XHTML 1.0 (strict), an XML document format that standardizes HTML.


完美了。这东西能解析HTML和CSS,而且能输出成image,PDF等格式。哇!我们来看看sample代码(代码丑陋,不过已经能说明问题了):

/* 
* ITextRendererTest.java * 
* Copyright 2009 Shanghai TuDou.  
* All rights reserved. 
*/

package itext;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import com.lowagie.text.pdf.BaseFont;

/** 
 * TODO class description * 
 *
 * @author pcwang
 *
 * @version 1.0, 上午11:03:26  create $Id$
 */
public class ITextRendererTest {
	public static void main(String[] args) throws Exception {
		String inputFile = "conf/template/test.html";
        String url = new File(inputFile).toURI().toURL().toString();
        String outputFile = "firstdoc.pdf";
        OutputStream os = new FileOutputStream(outputFile);
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocument(url);

        // 解决中文支持问题
        ITextFontResolver fontResolver = renderer.getFontResolver();
        fontResolver.addFont("C:/Windows/Fonts/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

        // 解决图片的相对路径问题
        renderer.getSharedContext().setBaseURL("file:/D:/Work/Demo2do/Yoda/branch/Yoda%20-%20All/conf/template/");
        
        renderer.layout();
        renderer.createPDF(os);
        
        os.close();
	}
}


运行,成功!实在太简单了!API帮你完成了一切!

有了这个东西,我们就可以将PDF的生成流程变成这样:

1) 编写Freemarker或者Velocity模板,打造HTML,勾画PDF的样式(请任意使用CSS)

2) 在你的业务逻辑层引入Freemarker的引擎或者Velocity的引擎,并将业务逻辑层中可以获取的数据和模板,使用引擎生成最终的内容

3) 将我上面的sample代码做简单封装后,调用,生成PDF

这样,我想作为一个web程序员来说,上面的3点,都不会成为你的绊脚石。你可以轻松驾驭PDF了。

在Flying Saucer的官方文档中,有一些Q&A,可以解决读者们大部分的问题。包括PDF的字体、PDF的格式、Image如何处理等等。大家可以尝试着去阅读。

还有一篇文章,好像是作者写的,非常不错:http://today.java.net/pub/a/today/2007/06/26/generating-pdfs-with-flying-saucer-and-itext.html
分享到:
评论
82 楼 l116116116 2010-01-29  
wuhongyan008 写道
问个问题啊?
有谁在websphere底下使用过flying sauser吗?我在websphere上用的是,发现css效果根本就没有显示出来,但用tomcat是可以准确生成的,哪位大侠知道怎么回事么?

...
title>cover-20091223</title>
<style type="text/css">
<!--

@import "theme/common.css";

...




看不太明白你的代码,
试试下面这种写法。
<link rel="stylesheet" href="<%=DBInfo.getWebServerPrefix()%>/css/common.css" />
81 楼 yye_javaeye 2010-01-28  
zjh0207 写道
包含有图片的html转pdf会出错
用<img src="">标签或用<input type="image" src="">都不行
控制台提示
“NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist.”

我用的是<img src="">最后带一个斜杠的,发帖出不来。。
80 楼 zjh0207 2010-01-27  
downpour,你下面代码中的那个url,具体是什么啊?
// 解决图片的相对路径问题  
        renderer.getSharedContext().setBaseURL("file:/D:/Work/Demo2do/Yoda/branch/Yoda%20-%20All/conf/template/");  
大家谁有好的方案,解决这带图片的html转pdf的问题
79 楼 zjh0207 2010-01-27  
包含有图片的html转pdf会出错
用<img src="">标签或用<input type="image" src="">都不行
控制台提示
“NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist.”
78 楼 zhangqh_zz 2010-01-26  
没有问题了,晕,是iText-2.0.8.jar 与我项目中的另旧版的包有冲突
77 楼 zhangqh_zz 2010-01-22  
我在测试时,出现如下错误,iText-2.0.8.jar core-renderer.jar
com.lowagie.text.pdf.BaseFont: method getCharBBox(C)[I not found
76 楼 xinhuayw 2010-01-21  
谢谢楼主分享!
  对于自动定报表格式,提供了一种方便的解决方案。
75 楼 watson1984 2010-01-21  
我在用flying saucer的时候,html的空格(&nbsp;)和js代码处理不好,不知道是什么原因~~
74 楼 wuhongyan008 2010-01-20  
问个问题啊?
有谁在websphere底下使用过flying sauser吗?我在websphere上用的是,发现css效果根本就没有显示出来,但用tomcat是可以准确生成的,哪位大侠知道怎么回事么?

...
title>cover-20091223</title>
<style type="text/css">
<!--

@import "theme/common.css";

...


73 楼 yye_javaeye 2010-01-06  
downpour 写道
yye_javaeye 写道
?怎么会?我用的是挺好的啊,效果看附件


帅哥,你不要光给我们一个jar包行吗?告诉我们一下,你改的哪个类,哪个方法,顺便把代码贴一下。谢谢啦。

呵呵,没注意到这个帖子,当时因为项目正着急,忘了贴上来了
修改了org.xhtmlrenderer.layout.Breaker类,添加了2个方法,修改了109行和121行,由原来的按空格分组改为调用getStrRight按新的方式分组来获取字符的右边界值:
/*
 * Breaker.java
 * Copyright (c) 2004, 2005 Torbj�rn Gannholm, 
 * Copyright (c) 2005 Wisconsin Court System
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */
package org.xhtmlrenderer.layout;

import org.xhtmlrenderer.css.constants.IdentValue;
import org.xhtmlrenderer.css.style.CalculatedStyle;
import org.xhtmlrenderer.render.FSFont;

/**
 * A utility class that scans the text of a single inline box, looking for the 
 * next break point.
 * @author Torbj�rn Gannholm
 */
public class Breaker {

    public static void breakFirstLetter(LayoutContext c, LineBreakContext context,
            int avail, CalculatedStyle style) {
        FSFont font = style.getFSFont(c);
        context.setEnd(getFirstLetterEnd(context.getMaster(), context.getStart()));
        context.setWidth(c.getTextRenderer().getWidth(
                c.getFontContext(), font, context.getCalculatedSubstring()));
        
        if (context.getWidth() > avail) {
            context.setNeedsNewLine(true);
            context.setUnbreakable(true);
        }
    }
    
    private static int getFirstLetterEnd(String text, int start) {
        int i = start;
        while (i < text.length()) {
            char c = text.charAt(i);
            int type = Character.getType(c);
            if (type == Character.START_PUNCTUATION || 
                    type == Character.END_PUNCTUATION ||
                    type == Character.INITIAL_QUOTE_PUNCTUATION ||
                    type == Character.FINAL_QUOTE_PUNCTUATION ||
                    type == Character.OTHER_PUNCTUATION) {
                i++;
            } else {
                break;
            }
        }
        if (i < text.length()) {
            i++;
        }
        return i;
    }    
    
    public static void breakText(LayoutContext c, 
            LineBreakContext context, int avail, CalculatedStyle style) {
        FSFont font = style.getFSFont(c);
        IdentValue whitespace = style.getWhitespace();
        
        // ====== handle nowrap
        if (whitespace == IdentValue.NOWRAP) {
        	context.setEnd(context.getLast());
        	context.setWidth(c.getTextRenderer().getWidth(
                    c.getFontContext(), font, context.getCalculatedSubstring()));
            return;
        }

        //check if we should break on the next newline
        if (whitespace == IdentValue.PRE ||
                whitespace == IdentValue.PRE_WRAP ||
                whitespace == IdentValue.PRE_LINE) {
            int n = context.getStartSubstring().indexOf(WhitespaceStripper.EOL);
            if (n > -1) {
                context.setEnd(context.getStart() + n + 1);
                context.setWidth(c.getTextRenderer().getWidth(
                        c.getFontContext(), font, context.getCalculatedSubstring()));
                context.setNeedsNewLine(true);
                context.setEndsOnNL(true);
            } else if (whitespace == IdentValue.PRE) {
            	context.setEnd(context.getLast());
                context.setWidth(c.getTextRenderer().getWidth(
                        c.getFontContext(), font, context.getCalculatedSubstring()));  
            }
        }

        //check if we may wrap
        if (whitespace == IdentValue.PRE || 
                (context.isNeedsNewLine() && context.getWidth() <= avail)) {
            return;
        }
        
        context.setEndsOnNL(false);

        String currentString = context.getStartSubstring();
        int left = 0;
//        int right = currentString.indexOf(WhitespaceStripper.SPACE, left + 1);
        int right = getStrRight(currentString,left);
        int lastWrap = 0;
        int graphicsLength = 0;
        int lastGraphicsLength = 0;

        while (right > 0 && graphicsLength <= avail) {
            lastGraphicsLength = graphicsLength;
            graphicsLength += c.getTextRenderer().getWidth(
                    c.getFontContext(), font, currentString.substring(left, right));
            lastWrap = left;
            left = right;
//            right = currentString.indexOf(WhitespaceStripper.SPACE, left + 1);
            right = getStrRight(currentString,left+1);
        }

        if (graphicsLength <= avail) {
            //try for the last bit too!
            lastWrap = left;
            lastGraphicsLength = graphicsLength;
            graphicsLength += c.getTextRenderer().getWidth(
                    c.getFontContext(), font, currentString.substring(left));
        }

        if (graphicsLength <= avail) {
            context.setWidth(graphicsLength);
            context.setEnd(context.getMaster().length());
            //It fit!
            return;
        }
        
        context.setNeedsNewLine(true);

        if (lastWrap != 0) {//found a place to wrap
            context.setEnd(context.getStart() + lastWrap);
            context.setWidth(lastGraphicsLength);
        } else {//unbreakable string
            if (left == 0) {
                left = currentString.length();
            }
            
            context.setEnd(context.getStart() + left);
            context.setUnbreakable(true);
            
            if (left == currentString.length()) {
                context.setWidth(c.getTextRenderer().getWidth(
                        c.getFontContext(), font, context.getCalculatedSubstring()));
            } else {
                context.setWidth(graphicsLength);
            }
        }
        return;
    }

    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }

    private static int getStrRight(String s,int left){
        if(left>=s.length())
            return -1;
        char[] ch = s.toCharArray();
        for(int i = left;i<ch.length;i++){
            if(isChinese(ch[i]) || ' ' == ch[i]){
                return i==0?i+1:i;
            }
        }
        return -1;
    }

}

72 楼 yye_javaeye 2010-01-06  
http://www.iteye.com/topic/509417?page=6#1279762
71 楼 wuhongyan008 2010-01-05  
yye_javaeye 写道
中文换行问题解决了,这东西源码里面是将英文按空格分组,每组判断其位置+长度是否超出边界,超出的话将该组丢到下一行,但是中文里面基本没有空格,所以就无奈了。
将其源码改了改,如果是中文,每字一组,如果是英文,还是按照空格分组,这样大概效率会受一些影响,不过好歹是可以用了,而且一般pdf生成我想应该也不会放在需要大访问量的地方吧。附件是打好包的jar,覆盖就可以了

怎么看不到你的附件了啊?哪位大侠能发我一份么?
70 楼 nathanlee 2009-12-15  
downpour 写道
flying sauser


股神,你无敌了
69 楼 Robert_Fanly 2009-12-15  
各位又沒有試過用loadjava 將iText-2.0.8.jar和core-renderer.jar 加載到 oracle 里面呢?
為啥我加載的時候報錯呢?如附件圖片

還有對繁體中文要怎樣設置字體呢?繁體中文出來都是亂碼。
68 楼 yye_javaeye 2009-12-15  
l116116116 写道
downpour 写道
l116116116 写道
最近要做一个 html的PDF打印的工作,看到了这篇文章,一直也在试图用flying saucer 的方案来实现。在整个过程中,遇到了很多困难,感觉flying saucer 本身在服务器端的解析能力,与浏览器通过http协议的解析能力还有很多的不足。 例如, 缩印,再例如,显示背景图片,再例如,对<table><tr><td>的支持,再例如对 <jsp:include/>,frame的支持(试过@include 语法,原来以为支持,结果也不支持。 难道只能渲染现有代码? )。 不知道大家在使用时感觉什么样。 之前我们曾使用过 客户端的小开源软件,pdf creator。 这个对客户端html的PDF解析相当有效。 美中不足的就是依赖于客户端的安装。 好好的瘦客户端变成胖客户端也有点不好。。。 唉~~~~~


我认为你这种试图使用JSP来渲染PDF的方式本身就和flying saucer的初衷不同。

Flying sauser的目标是能够解析基于HTML+CSS的plain text,并将之结构化成iText可识别的API调用。所以,你要做的,是把最终需要展现在PDF中的东西,用HTML+CSS表达出来,而不是传入给Flying sauser一个JSP文件。

所以我的看法是,Freemarker或者Velocity的模板才是使用Flying sauser的最佳实践。


我的表达有点问题,当然不是直接传入JSP,是把html的语言来用xhtml(说到底就是xml)来转化。我说的问题是在转化过程中遇到的问题。html+css 感觉非常适用于网站网页。

转化过程中怎么会跟jsp有关系呢?我用的是freemarker,对于freemarker的处理,在传到fs之前就已经结束了!
67 楼 l116116116 2009-12-14  
yye_javaeye 写道
现在的问题是,flying saucer 对于css的有些方法不支持,导致在pdf里面和浏览器里面的表现不一样,我对css也不熟,只能一点点儿改css了



相对于Jasper report,我觉得fly saucer的一大优点就是对css的支持。可能是因为浏览器和FS对css的解析不一样吧。
66 楼 l116116116 2009-12-14  
downpour 写道
l116116116 写道
最近要做一个 html的PDF打印的工作,看到了这篇文章,一直也在试图用flying saucer 的方案来实现。在整个过程中,遇到了很多困难,感觉flying saucer 本身在服务器端的解析能力,与浏览器通过http协议的解析能力还有很多的不足。 例如, 缩印,再例如,显示背景图片,再例如,对<table><tr><td>的支持,再例如对 <jsp:include/>,frame的支持(试过@include 语法,原来以为支持,结果也不支持。 难道只能渲染现有代码? )。 不知道大家在使用时感觉什么样。 之前我们曾使用过 客户端的小开源软件,pdf creator。 这个对客户端html的PDF解析相当有效。 美中不足的就是依赖于客户端的安装。 好好的瘦客户端变成胖客户端也有点不好。。。 唉~~~~~


我认为你这种试图使用JSP来渲染PDF的方式本身就和flying saucer的初衷不同。

Flying sauser的目标是能够解析基于HTML+CSS的plain text,并将之结构化成iText可识别的API调用。所以,你要做的,是把最终需要展现在PDF中的东西,用HTML+CSS表达出来,而不是传入给Flying sauser一个JSP文件。

所以我的看法是,Freemarker或者Velocity的模板才是使用Flying sauser的最佳实践。


我的表达有点问题,当然不是直接传入JSP,是把html的语言来用xhtml(说到底就是xml)来转化。我说的问题是在转化过程中遇到的问题。html+css 感觉非常适用于网站网页。
65 楼 yye_javaeye 2009-12-14  
现在的问题是,flying saucer 对于css的有些方法不支持,导致在pdf里面和浏览器里面的表现不一样,我对css也不熟,只能一点点儿改css了
64 楼 yye_javaeye 2009-12-14  
l116116116 写道
楼上的包我试过,加了一个 isChinese 的方法, 对于符合 xhtml语言的 DIV+CSS 样式的还是挺支持的,但对于不被推荐的<table><tr><td> 中的 中文字符貌似支持不了分行。详情见附件。



我是下面这种方法使用的:
<table width="100%" border="1" cellspacing="0" cellpadding="0" style="table-layout:fixed; word-break:break-strict;">
    <tr>
        <td>
            Jasper Report的设计思路,本身是不违反我上面所说的初衷的。因为我们的努力方向是先生成模板,然后得到数据,最后将两者整合得到结果。但是Jasper Report的问题在于,其生成模板的方式过于复杂,即使有IDE的帮助,我们还是需要对其中的众多规则有所了解才行,否则就会给调试带来极大的麻烦。
        </td>
    </tr>
    <tr>
        <td>
            Happy Thanksgiving!

            Given the holiday, we are releasing the President's weekly address today. 
            In this video, President Obama calls to our attention the men and women in uniform 
            who are away from home sacrificing time with family to protect our safety and freedom.
             He also talks about the progress of health care reform, the Recovery Act, and job creation to 
            ensure that next Thanksgiving will be a brighter day.


        </td>
    </tr>
</table>

没有发现问题啊
63 楼 downpour 2009-12-13  
l116116116 写道
最近要做一个 html的PDF打印的工作,看到了这篇文章,一直也在试图用flying saucer 的方案来实现。在整个过程中,遇到了很多困难,感觉flying saucer 本身在服务器端的解析能力,与浏览器通过http协议的解析能力还有很多的不足。 例如, 缩印,再例如,显示背景图片,再例如,对<table><tr><td>的支持,再例如对 <jsp:include/>,frame的支持(试过@include 语法,原来以为支持,结果也不支持。 难道只能渲染现有代码? )。 不知道大家在使用时感觉什么样。 之前我们曾使用过 客户端的小开源软件,pdf creator。 这个对客户端html的PDF解析相当有效。 美中不足的就是依赖于客户端的安装。 好好的瘦客户端变成胖客户端也有点不好。。。 唉~~~~~


我认为你这种试图使用JSP来渲染PDF的方式本身就和flying saucer的初衷不同。

Flying sauser的目标是能够解析基于HTML+CSS的plain text,并将之结构化成iText可识别的API调用。所以,你要做的,是把最终需要展现在PDF中的东西,用HTML+CSS表达出来,而不是传入给Flying sauser一个JSP文件。

所以我的看法是,Freemarker或者Velocity的模板才是使用Flying sauser的最佳实践。

相关推荐

    itext的PDF生成方案

    **iText PDF生成方案** iText是一个开源的Java库,专门用于创建和修改PDF文档。在IT领域,尤其是在文档处理和报告生成方面,iText是一个非常实用的工具。本方案将详细探讨如何利用iText来生成PDF文件,以及相关的...

    QT5生成PDF

    1、 pdfWriter1():使用QpdfWriter和Qpainter进行纯文字版的pdf生成和绘制,并进行了分页显示。 Pdf生成在当前目录下的pdf_test.pdf 2、 pdfWriter2():使用QPdfwriter 和QPainter创建pdf报告,关键是对页面的布局...

    MCU生成PDF文件

    首先,我们需要一个PDF库,它能够运行在资源有限的MCU上。虽然PDF格式复杂,但有一些轻量级的开源库如`PDFGen`可以帮助我们实现这一目标。根据提供的压缩包包名`PDFGen-master`,我们可以假设这是我们要用的库,它...

    java 多个pdf合并,目录生成(支持自定义目录),页码生成(源码)

    本项目提供了一个纯Java实现的解决方案,它能有效地完成多个PDF文件的合并,并且支持自定义目录的生成以及页码的添加。 首先,`PDFUtil.java`是这个项目的核心类,它包含了处理PDF的关键方法。PDFUtil可能包含了...

    pdf生成缩略图

    PDF生成缩略图是将PDF文档中的页面转换成小尺寸的图像表示,通常用于预览、索引或在文件管理器中快速查看PDF内容。在IT领域,这涉及到PDF处理和图像处理技术。以下是一些关于如何在C#中生成PDF缩略图的关键知识点: ...

    自动生成PDF文件,C#源码

    标题“自动生成PDF文件,C#源码”表明我们讨论的是一个使用C#编程语言创建PDF文件的解决方案。这通常涉及到第三方库的使用,如iTextSharp,它是一个强大的PDF处理库,能够帮助开发者在C#环境中方便地生成、编辑和...

    Java将PDF生成图片

    以下是一些关于“Java将PDF生成图片”的核心知识点: 1. **PDF处理库**:在Java中,我们可以使用第三方库如Apache PDFBox、iText和PDF Clown等来处理PDF文档。这些库提供了丰富的API,用于读取、解析和操作PDF文件...

    PDF生成器for win7

    此外,PDF生成器还可能提供一些高级特性,如合并多个文件为一个PDF、添加水印、密码保护等,以满足不同用户的需求。 总的来说,PDF生成器是Windows 7用户便捷创建PDF文档的重要工具。通过理解其工作原理和使用方法...

    多图片生成一PDF工具.zip

    总的来说,这款“多图片生成一PDF工具”提供了一个简单易用且高效的解决方案,帮助用户快速将图片集合整理成PDF文档,特别适合处理jpg、png和bmp格式的图片。同时,其批量处理功能极大地提升了处理大量图片的效率。...

    C#生成pdf文件

    虽然.NET Framework本身并不直接支持PDF生成,但有许多开源和商业库可供选择,如iTextSharp、PDFsharp、Syncfusion Essential PDF等。这些库提供了API,允许开发者创建、编辑和操作PDF文档。 以iTextSharp为例,这...

    PDF生成器包含注册码

    总的来说,这款包含注册码的PDF生成器提供了一个便捷的解决方案,帮助用户轻松创建和管理PDF文档。其小巧的体积、简单的操作以及全面的功能使得它成为处理PDF文件的理想选择。用户在享受这些服务的同时,也无需担心...

    保护数据隐私的深度学习训练数据生成方案.pdf

    本文主要介绍了一种保护数据隐私的深度学习训练数据生成方案,该方案基于条件生成对抗网络(CGAN),能够生成大量与真实数据同分布的对抗样本,满足了生成大量带标签训练数据的需求。同时,该方案还结合数据变形方法...

    php完全生成pdf解决方案

    php生成pdf的完全解决方案,不使用phplib插件,完全脚本化执行,完美解决中文乱码问题,支持以下功能: 1、完美支持中文,php生成的pdf不会出现乱码 2、把SQL查询结构生成为pdf中的表格 3、pdf页眉页脚支持中文及...

    在c#中生成PDF文件

    首先,我们需要一个库来处理PDF生成。一个常用的开源库是iTextSharp,它是一个功能丰富的PDF处理库,支持多种操作,包括创建、编辑和读取PDF文件。要使用iTextSharp,你需要在项目中添加对它的引用。可以通过NuGet包...

    itextpdf.zip(JavaPDF文件生成)

    JavaPDF文件生成是Java开发中一个重要的领域,主要用于创建、编辑和处理PDF文档。iTextPDF是一个流行的开源库,它提供了丰富的API...通过熟练掌握iTextPDF,开发者可以在Java应用程序中实现专业级的PDF生成和处理功能。

    java生成PDF417条码

    4. **集成到应用**:将条码生成功能集成到你的Java应用程序中,可能需要创建一个服务或工具类,提供生成条码的接口。这可能涉及到处理用户输入、验证数据、选择条码格式,以及将生成的条码图像插入到PDF、报告或网页...

    一款很好的PDF组件(ASP生成PDF)

    【ASP PDF组件与PDF生成技术】 在Web开发中,生成PDF文档是一项常见的需求,用于提供打印友好版本或者方便用户下载的格式。ASP(Active Server Pages)是微软开发的一种服务器端脚本环境,常用于构建动态网页。而...

    利用freemarker 模板生成pdf ,利用easypoi 生成excel(带图片,水印,分页)

    在生成PDF时,我们可以借助Flying Saucer库,这是一个能够将HTML转换为PDF的工具。通过将Freemarker模板与Flying Saucer结合,可以方便地将动态数据转换成结构化的PDF文档。例如,你可以创建一个Freemarker模板,...

    freemarker生成doc方案.pdf(内附代码下载地址)

    在当今的信息技术领域,自动化文档生成是一个非常重要的功能,尤其是在企业和监管单位中,自动化的文档生成可以节省大量的人力和时间资源,提高工作效率。为了实现这一目标,使用Freemarker模板引擎结合Office软件...

    简单易用的pdf生成器

    总之,"简单易用的pdf生成器"通过DOPDF提供了一个便捷的解决方案,使得用户能够快速且轻松地将Word文档转换为PDF,确保内容的准确性和安全性。通过掌握这种工具的使用,无论是个人还是专业人士,都能在日常工作中...

Global site tag (gtag.js) - Google Analytics