Html字符串生成pdf的方法 支持中文及中文换行 可行demo和jar

时间: 2023-07-11 admin 互联网

Html字符串生成pdf的方法 支持中文及中文换行 可行demo和jar

Html字符串生成pdf的方法 支持中文及中文换行 可行demo和jar

中文换行修改好后的jar:
pdf.JS
一:遇到的问题;
1、 中文不支持
2、 中文不换行
3、 如何显示
4、 不显示签章

二:生成(根据html字符串来生成pdf,方便我们的替换)
下边是应用itext进行编写的生成pdf代码(这里要支持中文需要导入相应的iTextAsian jar包)

public static void myContractPdf(String template,long investid)throws DocumentException, IOException{
String outputFile = Play.applicationPath+File.separator+“ssqFile”+File.separator+String.valueOf(investid)+".pdf";
FileOutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(Play.applicationPath+File.separator+“public”+File.separator+“pdfjs”+File.separator+“font”+File.separator+“simsun.ttc”, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
StringBuffer html = new StringBuffer();
// DOCTYPE 必需写否则类似于 这样的字符解析会出现错误
html.append("");
html.append("").append("")
.append("")
.append(“”)
.append("")
.append("");
html.append(repaceContractTemplate(template, investid));
html.append("");
renderer.setDocumentFromString(html.toString());
renderer.layout();
renderer.createPDF(os);
os.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
这时我们已经生成了一份支持中文的pdf。但是我们会发现他并没对中文进行换行,好多文本已经超出界限丢失了。
三、中文换行
原因就是这itaxt是国外编写的。对中文的支持并不好,它是对空格惊醒换行的,而中文却不是,所以我们就需要改变一下源代码,让其支持中文
重写Breaker,添加中文识别。

  1. // Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
  2. // Jad home page: .html
  3. // Decompiler options: packimports(3) fieldsfirst ansi space
  4. // Source File Name: Breaker.java
  5. package org.xhtmlrenderer.layout;
  6. import java.text.BreakIterator;
  7. import org.xhtmlrenderer.css.constants.IdentValue;
  8. import org.xhtmlrenderer.css.style.CalculatedStyle;
  9. import org.xhtmlrenderer.extend.TextRenderer;
  10. // Referenced classes of package org.xhtmlrenderer.layout:
  11. // LineBreakContext, LayoutContext
  12. public class Breaker
  13. {
  14. public Breaker()
  15. {
  16. }
  17. public static void breakFirstLetter(LayoutContext c, LineBreakContext context, int avail, CalculatedStyle style)
  18. {
  19. org.xhtmlrenderer.render.FSFont font = style.getFSFont©;
  20. context.setEnd(getFirstLetterEnd(context.getMaster(), context.getStart()));
  21. context.setWidth(c.getTextRenderer().getWidth(c.getFontContext(), font, context.getCalculatedSubstring()));
  22. if (context.getWidth() > avail)
  23. {
  24. context.setNeedsNewLine(true);
  25. context.setUnbreakable(true);
  26. }
  27. }
  28. private static int getFirstLetterEnd(String text, int start)
  29. {
  30. int i = start;
  31. do
  32. {
  33. if (i >= text.length())
  34. break;
  35. char c = text.charAt(i);
  36. int type = Character.getType©;
  37. if (type != 21 && type != 22 && type != 29 && type != 30 && type != 24)
  38. break;
  39. i++;
  40. } while (true);
  41. if (i < text.length())
  42. i++;
  43. return i;
  44. }
  45. public static void breakText(LayoutContext c, LineBreakContext context, int avail, CalculatedStyle style)
  46. {
  47. org.xhtmlrenderer.render.FSFont font = style.getFSFont©;
  48. IdentValue whitespace = style.getWhitespace();
  49. if (whitespace == IdentValue.NOWRAP)
  50. {
  51. context.setEnd(context.getLast());
  52. context.setWidth(c.getTextRenderer().getWidth(c.getFontContext(), font, context.getCalculatedSubstring()));
  53. return;
  54. }
  55. if (whitespace == IdentValue.PRE || whitespace == IdentValue.PRE_WRAP || whitespace == IdentValue.PRE_LINE)
  56. {
  57. int n = context.getStartSubstring().indexOf("\n");
  58. if (n > -1)
  59. {
  60. context.setEnd(context.getStart() + n + 1);
  61. context.setWidth(c.getTextRenderer().getWidth(c.getFontContext(), font, context.getCalculatedSubstring()));
  62. context.setNeedsNewLine(true);
  63. context.setEndsOnNL(true);
  64. } else
  65. if (whitespace == IdentValue.PRE)
  66. {
  67. context.setEnd(context.getLast());
  68. context.setWidth(c.getTextRenderer().getWidth(c.getFontContext(), font, context.getCalculatedSubstring()));
  69. }
  70. }
  71. if (whitespace == IdentValue.PRE || context.isNeedsNewLine() && context.getWidth() <= avail)
  72. return;
  73. context.setEndsOnNL(false);
  74. String currentString = context.getStartSubstring();
  75. int left = 0;
  76. int right = getStrRight(currentString,left+1);
  77. int lastWrap = 0;
  78. int graphicsLength = 0;
  79. int lastGraphicsLength = 0;
  80. for (; right > 0 && graphicsLength <= avail; right =getStrRight(currentString,left+1))
  81. {
  82. lastGraphicsLength = graphicsLength;
  83. graphicsLength += c.getTextRenderer().getWidth(c.getFontContext(), font, currentString.substring(left, right));
  84. lastWrap = left;
  85. left = right;
  86. }
  87. if (graphicsLength <= avail)
  88. {
  89. lastWrap = left;
  90. lastGraphicsLength = graphicsLength;
  91. graphicsLength += c.getTextRenderer().getWidth(c.getFontContext(), font, currentString.substring(left));
  92. }
  93. if (graphicsLength <= avail)
  94. {
  95. context.setWidth(graphicsLength);
  96. context.setEnd(context.getMaster().length());
  97. return;
  98. }
  99. context.setNeedsNewLine(true);
  100. if (lastWrap != 0)
  101. {
  102. context.setEnd(context.getStart() + lastWrap);
  103. context.setWidth(lastGraphicsLength);
  104. } else
  105. {
  106. if (left == 0)
  107. left = currentString.length();
  108. context.setEnd(context.getStart() + left);
  109. context.setUnbreakable(true);
  110. if (left == currentString.length())
  111. context.setWidth(c.getTextRenderer().getWidth(c.getFontContext(), font, context.getCalculatedSubstring()));
  112. else
  113. context.setWidth(graphicsLength);
  114. }
  115. }
  116. public static BreakIterator getWordStream(String s) {
  117. BreakIterator i = BreakIterator.getWordInstance();
  118. i.setText(s);
  119. return i;
  120. }
  121. /**
    • 判断是否是中文
    • @param c
    • @return
  122. */
  123. private static boolean isChinses(char c){
  124. Character.UnicodeBlock ub=Character.UnicodeBlock.of©;
  125. if(ub==Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
  126. || ub==Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
  127. || ub==Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
  128. || ub==Character.UnicodeBlock.GENERAL_PUNCTUATION
  129. || ub==Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
  130. || ub==Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS ){
  131. return true;
  132. }
  133. return false;
  134. }
  135. /**
    • 替换原先本类中所以获取right的方法
    • int right = getStrRight(currentString,left+1);
    • @param s
    • @param left
    • @return
  136. */
  137. private static int getStrRight(String s,int left){
  138. if(left>=s.length())
  139. return -1;
  140. char[] ch=s.toCharArray();
  141. for(int i=left;i<ch.length;i++){
  142. if(isChinses(ch[i]) || ‘\0’==ch[i]){
  143. return i==0?i+1:i;
  144. }
  145. }
  146. return -1;
  147. }
  148. }
    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
    至于怎么修改源码,请自行百度,下方提供已经修改好的jar。
    修改好后的jar:
    四、web查看
    现在生成了pdf,那么我们咋么在前端更好的展现pdf 呢,在这里我们就要用到pdfjs来帮助我们展示pdf
    下载好pdf.JS

    `部署完成
    好了 我们可应用viewer.html进行展示
    在viewer中引入正确的引导。在这里我们应用base64进行显示。
    在viewer中写入下面js。根据自己的环境进行修改。这里应用的是play框架。

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
后台

byte[] bb=(pdf的流)
返回com.lowagie.text.pdf.codec.Base64.encodeBytes(bb)
1
2
3
下边的截图是控制展示的pdf的样式

到此之后 我们的生成和查看就实现了。而且是我们可控的。
五、显示签章
但是我们会发现 有签名的话 会不显示,这里我们要改一下
将pdf.js源码下载后,在build/pdf.worker.js文件中找到如下图所示的代码段

将this.setFlags(AnnotationFlag.HIDDEN);注释掉就会显示电子签章,反之不显示。
————————————————
版权声明:本文为CSDN博主「天才之上」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接: