目录:
- 概述
- 软件要求
- 实现过程
[一]、概述
前面已经介绍了如何实现对HTML中文字符的转换以及HTML文件生成PDF文件的基本方法,本文主要演示下如何把URL地址对应的内容直接转换生成PDF文件,这个需求也有很多的应用场景,最简单的应用场景比如:自己blog中的文章如何转PDF,如果能生成PDF文件,一方面可以方便自己的阅读,亦可作为一种备份。
[二]、软件要求
- 如何URL地址内容包含中文字符,需要XML Worker能支持中文字符转换(详见:http://www.micmiu.com/opensource/expdoc/itext-xml-worker-cn/)
- Java 的HTML解析器,这里选择 :jsoup (官网:http://jsoup.org/),如果是 maven 构建项目的,直接在pom文件中增加jsoup的依赖配置即可:
1234567<dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.7.1</version><type>jar</type><scope>compile</scope></dependency>
[三]、实现过程
以我的blog:http://www.micmiu.com/os/linux/shell-dev-null/ 为例,和HTML文件转PDF类似同样有两种方法,详细介绍见下面的具体实现代码中的注释。
Java实现代码:Demo4URL2PDF.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
package com.micmiu.pdf.itext; import java.io.ByteArrayInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.jsoup.Jsoup; import com.itextpdf.text.BaseColor; import com.itextpdf.text.Chapter; import com.itextpdf.text.Chunk; import com.itextpdf.text.Document; import com.itextpdf.text.Element; import com.itextpdf.text.Font; import com.itextpdf.text.PageSize; import com.itextpdf.text.Paragraph; import com.itextpdf.text.Section; import com.itextpdf.text.WritableDirectElement; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfWriter; import com.itextpdf.text.pdf.draw.LineSeparator; import com.itextpdf.tool.xml.ElementHandler; import com.itextpdf.tool.xml.Writable; import com.itextpdf.tool.xml.XMLWorkerHelper; import com.itextpdf.tool.xml.pipeline.WritableElement; /** * HTML文件转换为PDF * * @author <a href="http://www.micmiu.com">Michael Sun</a> */ public class Demo4URL2PDF { /** * @param args */ public static void main(String[] args) throws Exception { String blogURL = "http://www.micmiu.com/os/linux/shell-dev-null/"; // 直接把网页内容转为PDF文件 String pdfFile = "d:/test/itext/demo-URL.pdf"; Demo4URL2PDF.parseURL2PDFFile(pdfFile, blogURL); // 把网页内容转为PDF中的Elements String pdfFile2 = "d:/test/itext/demo-URL2.pdf"; Demo4URL2PDF.parseURL2PDFElement(pdfFile2, blogURL); } /** * 根据URL提前blog的基本信息,返回结果>>:[主题 ,分类,日期,内容]等. * * @param blogURL * @return * @throws Exception */ public static String[] extractBlogInfo(String blogURL) throws Exception { String[] info = new String[4]; org.jsoup.nodes.Document doc = Jsoup.connect(blogURL).get(); org.jsoup.nodes.Element e_title = doc.select("h2.title").first(); info[0] = e_title.text(); org.jsoup.nodes.Element e_category = doc.select("a[rel=category tag]") .first(); info[1] = e_category.attr("href").replace("http://www.micmiu.com/", ""); org.jsoup.nodes.Element e_date = doc.select("span.post-info-date") .first(); String dateStr = e_date.text().split("日期")[1].trim(); info[2] = dateStr; org.jsoup.nodes.Element entry = doc.select("div.entry").first(); info[3] = formatContentTag(entry); return info; } /** * 格式化 img标签 * * @param entry * @return */ private static String formatContentTag(org.jsoup.nodes.Element entry) { try { entry.select("div").remove(); // 把 <a href="*.jpg" ><img src="*.jpg"/></a> 替换为 <img // src="*.jpg"/> for (org.jsoup.nodes.Element imgEle : entry .select("a[href~=(?i)\\.(png|jpe?g)]")) { imgEle.replaceWith(imgEle.select("img").first()); } return entry.html(); } catch (Exception e) { return ""; } } /** * 把String 转为 InputStream * * @param content * @return */ public static InputStream parse2Stream(String content) { try { ByteArrayInputStream stream = new ByteArrayInputStream( content.getBytes("utf-8")); return stream; } catch (Exception e) { return null; } } /** * 直接把网页内容转为PDF文件 * * @param fileName * @throws Exception */ public static void parseURL2PDFFile(String pdfFile, String blogURL) throws Exception { BaseFont bfCN = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", false); // 中文字体定义 Font chFont = new Font(bfCN, 14, Font.NORMAL, BaseColor.BLUE); Font secFont = new Font(bfCN, 12, Font.NORMAL, new BaseColor(0, 204, 255)); Font textFont = new Font(bfCN, 12, Font.NORMAL, BaseColor.BLACK); Document document = new Document(); PdfWriter pdfwriter = PdfWriter.getInstance(document, new FileOutputStream(pdfFile)); pdfwriter.setViewerPreferences(PdfWriter.HideToolbar); document.open(); String[] blogInfo = extractBlogInfo(blogURL); int chNum = 1; Chapter chapter = new Chapter(new Paragraph("URL转PDF测试", chFont), chNum++); Section section = chapter .addSection(new Paragraph(blogInfo[0], secFont)); section.setIndentation(10); section.setIndentationLeft(10); section.setBookmarkOpen(false); section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT); section.add(new Chunk("分类:" + blogInfo[1] + " 日期:" + blogInfo[2], textFont)); LineSeparator line = new LineSeparator(1, 100, new BaseColor(204, 204, 204), Element.ALIGN_CENTER, -2); Paragraph p_line = new Paragraph(" "); p_line.add(line); section.add(p_line); section.add(Chunk.NEWLINE); document.add(chapter); // html文件 XMLWorkerHelper.getInstance().parseXHtml(pdfwriter, document, parse2Stream(blogInfo[3])); document.close(); } /** * 把网页内容转为PDF中的Elements * * @param pdfFile * @param htmlFileStream */ public static void parseURL2PDFElement(String pdfFile, String blogURL) { try { Document document = new Document(PageSize.A4); FileOutputStream outputStream = new FileOutputStream(pdfFile); PdfWriter pdfwriter = PdfWriter.getInstance(document, outputStream); // pdfwriter.setViewerPreferences(PdfWriter.HideToolbar); document.open(); BaseFont bfCN = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", false); // 中文字体定义 Font chFont = new Font(bfCN, 14, Font.NORMAL, BaseColor.BLUE); Font secFont = new Font(bfCN, 12, Font.NORMAL, new BaseColor(0, 204, 255)); Font textFont = new Font(bfCN, 12, Font.NORMAL, BaseColor.BLACK); int chNum = 1; Chapter chapter = new Chapter(new Paragraph("URL转PDF元素,便于追加其他内容", chFont), chNum++); String[] blogInfo = extractBlogInfo(blogURL); Section section = chapter.addSection(new Paragraph(blogInfo[0], secFont)); section.setIndentation(10); section.setIndentationLeft(10); section.setBookmarkOpen(false); section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT); section.add(new Chunk("分类:" + blogInfo[1] + " 发表日期:" + blogInfo[2], textFont)); LineSeparator line = new LineSeparator(1, 100, new BaseColor(204, 204, 204), Element.ALIGN_CENTER, -2); Paragraph p_line = new Paragraph(); p_line.add(line); section.add(p_line); section.add(Chunk.NEWLINE); final List<Element> pdfeleList = new ArrayList<Element>(); ElementHandler elemH = new ElementHandler() { public void add(final Writable w) { if (w instanceof WritableElement) { pdfeleList.addAll(((WritableElement) w).elements()); } } }; XMLWorkerHelper.getInstance().parseXHtml(elemH, new InputStreamReader(parse2Stream(blogInfo[3]), "utf-8")); List<Element> list = new ArrayList<Element>(); for (Element ele : pdfeleList) { if (ele instanceof LineSeparator || ele instanceof WritableDirectElement) { continue; } list.add(ele); } section.addAll(list); section = chapter.addSection(new Paragraph("继续添加章节", secFont)); section.setIndentation(10); section.setIndentationLeft(10); section.setBookmarkOpen(false); section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT); section.add(new Chunk("测试URL转为PDF元素,方便追加其他内容", textFont)); document.add(chapter); document.close(); } catch (Exception e) { e.printStackTrace(); } } } |
运行后生成的两个PDF的效果如下:
从上面的效果图可见:根据URL地址生成的PDF和浏览器中页面效果以及之前HTML文件生成的PDF效果完全一致。
本文介绍到此结束@Michael Sun.
原创文章,转载请注明: 转载自micmiu – 软件开发+生活点滴[ http://www.micmiu.com/ ]
本文链接地址: http://www.micmiu.com/opensource/expdoc/itext-url-pdf/
com.itextpdf.tool.xml.html.pdfelement.NoNewLineParagraph.setMultipliedLeading(F)V
shell /dev/null 2>&1 /dev/null ,
[]
>/dev/null 2>&1
> echo “micmiu.com” > /home/michaeltest.txt
/dev/null
2> stderr
& 2>&121
1 stdout1”>/dev/null” “1>/dev/null”
”>/dev/null 2>&1 “1>/dev/null 2>&1
[]
1>/dev/null
2>&1
@Michael Sun
我生成PDF文件,中文全部消失 为什么
我的也是中文不显示,你是怎么解决的?谢谢!
上面有解决办法链接http://www.micmiu.com/opensource/expdoc/itext-xml-worker-cn/
执行出现此异常,求指点啊
Exception in thread “main” com.itextpdf.tool.xml.exceptions.RuntimeWorkerException: Invalid nested tag span found, expected closing tag br.
at com.itextpdf.tool.xml.XMLWorker.endElement(XMLWorker.java:135)
at com.itextpdf.tool.xml.parser.XMLParser.endElement(XMLParser.java:397)
at com.itextpdf.tool.xml.parser.state.ClosingTagState.process(ClosingTagState.java:71)
at com.itextpdf.tool.xml.parser.XMLParser.parseWithReader(XMLParser.java:237)
at com.itextpdf.tool.xml.parser.XMLParser.parse(XMLParser.java:215)
at com.itextpdf.tool.xml.parser.XMLParser.parse(XMLParser.java:176)
at com.itextpdf.tool.xml.XMLWorkerHelper.parseXHtml(XMLWorkerHelper.java:226)
at com.itextpdf.tool.xml.XMLWorkerHelper.parseXHtml(XMLWorkerHelper.java:184)
at com.zzzhc.common.utils.Demo4URL2PDF.parseURL2PDFFile(Demo4URL2PDF.java:165)
at com.zzzhc.common.utils.Demo4URL2PDF.main(Demo4URL2PDF.java:45)
我也是,你解决了吗
求解,为什么会空指针异常?
Exception in thread “main” java.lang.NullPointerException
at liulanqi.Demo4URL2PDF.extractBlogInfo(Demo4URL2PDF.java:61)
at liulanqi.Demo4URL2PDF.parseURL2PDFFile(Demo4URL2PDF.java:139)
at liulanqi.Demo4URL2PDF.main(Demo4URL2PDF.java:45)
亲能把使用的jar 告诉下吗?
什么jar?
导出你这篇文章就出现空指针异常了
String blogURL = “http://www.micmiu.com/opensource/expdoc/itext-url-pdf/”;
Exception in thread “main” java.lang.NullPointerException
at Demo4URL2PDF.extractBlogInfo(Demo4URL2PDF.java:48)
at Demo4URL2PDF.parseURL2PDFFile(Demo4URL2PDF.java:111)
atDemo4URL2PDF.main(Demo4URL2PDF.java:30)
你的行号和具体的代码要给我看下,你的错误提示不一致
Exception in thread “main” java.lang.NullPointerException
at liulanqi.Demo4URL2PDF.extractBlogInfo(Demo4URL2PDF.java:61)
at liulanqi.Demo4URL2PDF.parseURL2PDFFile(Demo4URL2PDF.java:139)
at liulanqi.Demo4URL2PDF.main(Demo4URL2PDF.java:45)
哎,是包的问题,那是老的包,我网上下了一个itext-asian-5.2.0的包,问题解决了,我那个是2.0的版本,谢谢大神,加你微博关注了,有问题可以发微博咨询么?
当然可以
Font ‘STSongStd-Light’ with ‘UniGB-UCS2-H’ is not recognized.
总是出现这个错误,怎么解决啊?
你字体的jar包 是否添加到项目中?
文字jar包加入了其中,iTextAsian加入了,并且按照网上的说法,把iTextAsian中的路径改为了itextpdf,还是总是报Font ‘STSongStd-Light’ with ‘UniGB-UCS2-H’ is not recognized.
不要修改路径啊 那个是老版本才有的问题
我用的是itextpdf-5.3.5的jar包,然后iTextAsian里面不管改不改路径都会出现,编码上的问题,困扰了一早上啊,求大神解释。
我的是itextpdf-5.3.3 itext-asian-5.2.0 没有任何问题哇
你按照 blog itext入门 中的中文输出试试的