Java解決Itext pdf中文不顯示問題
最近在專案需要,需要將html內容轉換成pdf的檔案,採用itextpdf總是不顯示中文。
找了很多方法都沒搞定,然後在網上看到了有個帖子說改原始碼解決這個問題,但是經過測試還是沒有搞定。
並且個人不建議改原始碼,然後自己研究原始碼,借鑑了他的思路,可以不用改原始碼即可解決中文問題。
第一部:
maven 引入依賴的jar包
根據ChunkCssApplier重寫apply方法
新增一個ParserHTML.java
模板 hero.html
找了很多方法都沒搞定,然後在網上看到了有個帖子說改原始碼解決這個問題,但是經過測試還是沒有搞定。
並且個人不建議改原始碼,然後自己研究原始碼,借鑑了他的思路,可以不用改原始碼即可解決中文問題。
第一部:
maven 引入依賴的jar包
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.9</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.9</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
根據ChunkCssApplier重寫apply方法
@SuppressWarnings("deprecation")
public class MyChunkCssApplier extends ChunkCssApplier {
public static BaseFont chinessFont = null;
static {
try {
// 中文支援,需要引入 itext-asian.jar
chinessFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 判斷是否存在中文
* @param str
* @return
*/
private static boolean isChinese(String str){
if(str == null ){
return false;
}
//存在中文
String regex = ".*[\\u4e00-\\u9faf].*";
return Pattern.matches(regex, str);
}
/**
*
* 重寫apply方法
*/
@Override
public Chunk apply(Chunk c, Tag t) {
Font f = applyFontStyles(t);
// 增加此段程式碼 如果中文 ,則返回中文字型
if (null != chinessFont && isChinese(c.getContent())) {
f = new Font(chinessFont, f.getSize(), f.getStyle(), f.getColor());
}
// 下面程式碼從原始碼中copy
float size = f.getSize();
Map<String, String> rules = t.getCSS();
for (Entry<String, String> entry : rules.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (CSS.Property.FONT_STYLE.equalsIgnoreCase(key)) {
if (value.equalsIgnoreCase(CSS.Value.OBLIQUE)) {
c.setSkew(0, 12);
}
} else if (CSS.Property.LETTER_SPACING.equalsIgnoreCase(key)) {
String letterSpacing = rules.get(CSS.Property.LETTER_SPACING);
float letterSpacingValue = 0f;
if (utils.isRelativeValue(value)) {
letterSpacingValue = utils.parseRelativeValue(letterSpacing, f.getSize());
} else if (utils.isMetricValue(value)){
letterSpacingValue = utils.parsePxInCmMmPcToPt(letterSpacing);
}
c.setCharacterSpacing(letterSpacingValue);
} else if (null != rules.get(CSS.Property.XFA_FONT_HORIZONTAL_SCALE)) { // only % allowed; need a catch block NumberFormatExc?
c.setHorizontalScaling(Float.parseFloat(rules.get(CSS.Property.XFA_FONT_HORIZONTAL_SCALE).replace("%", "")) / 100);
}
}
// following styles are separate from the for each loop, because they are based on font settings like size.
if (null != rules.get(CSS.Property.VERTICAL_ALIGN)) {
String value = rules.get(CSS.Property.VERTICAL_ALIGN);
if (value.equalsIgnoreCase(CSS.Value.SUPER) || value.equalsIgnoreCase(CSS.Value.TOP) || value.equalsIgnoreCase(CSS.Value.TEXT_TOP)) {
c.setTextRise((float) (size / 2 + 0.5));
} else if (value.equalsIgnoreCase(CSS.Value.SUB) || value.equalsIgnoreCase(CSS.Value.BOTTOM) || value.equalsIgnoreCase(CSS.Value.TEXT_BOTTOM)) {
c.setTextRise(-size / 2);
} else {
c.setTextRise(utils.parsePxInCmMmPcToPt(value));
}
}
String xfaVertScale = rules.get(CSS.Property.XFA_FONT_VERTICAL_SCALE);
if (null != xfaVertScale) {
if (xfaVertScale.contains("%")) {
size *= Float.parseFloat(xfaVertScale.replace("%", "")) / 100;
c.setHorizontalScaling(100 / Float.parseFloat(xfaVertScale.replace("%", "")));
}
}
if (null != rules.get(CSS.Property.TEXT_DECORATION)) {
String[] splitValues = rules.get(CSS.Property.TEXT_DECORATION).split("\\s+");
for (String value : splitValues) {
if (CSS.Value.UNDERLINE.equalsIgnoreCase(value)) {
c.setUnderline(null, 0.75f, 0, 0, -0.125f, PdfContentByte.LINE_CAP_BUTT);
}
if (CSS.Value.LINE_THROUGH.equalsIgnoreCase(value)) {
c.setUnderline(null, 0.75f, 0, 0, 0.25f, PdfContentByte.LINE_CAP_BUTT);
}
}
}
if (null != rules.get(CSS.Property.BACKGROUND_COLOR)) {
c.setBackground(HtmlUtilities.decodeColor(rules.get(CSS.Property.BACKGROUND_COLOR)));
}
f.setSize(size);
c.setFont(f);
Float leading = null;
if(rules.get(CSS.Property.LINE_HEIGHT) != null) {
String value = rules.get(CSS.Property.LINE_HEIGHT);
if(utils.isNumericValue(value)) {
leading = Float.parseFloat(value) * c.getFont().getSize();
} else if (utils.isRelativeValue(value)) {
leading = utils.parseRelativeValue(value, c.getFont().getSize());
} else if (utils.isMetricValue(value)){
leading = utils.parsePxInCmMmPcToPt(value);
}
}
if (leading != null) {
c.setLineHeight(leading);
}
return c;
}
}
新增一個ParserHTML.java
/**
* Hello world!
*
*/
public class ParserHTML
{
public static final String HTML = "D:/test/hero.html";
public static final String DEST = "D:/test/hero.pdf";
// public static final String HTML = "resources/xml/hero2.html";
// public static final String DEST = "results/xmlworker/asian2.pdf";
/**
* Creates a PDF with the words "Hello World"
* @param file
* @throws IOException
* @throws DocumentException
*/
public void createPdf(String file) throws IOException, DocumentException {
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
// step 3
document.open();
// step 4
// CSS
CSSResolver cssResolver = new StyleAttrCSSResolver();
CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream("body {font-family:tsc fming s tt}".getBytes()));
cssResolver.addCss(cssFile);
// 將ChunkCssApplier 設定為自定義的
CssAppliers cssAppliers = new CssAppliersImpl();
cssAppliers.setChunkCssAplier(new MyChunkCssApplier());
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
// Pipelines
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
// XML Worker
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.parse(new FileInputStream(HTML), Charset.forName("UTF-8"));
// step 5
document.close();
}
/**
* Main method
*/
public static void main(String[] args) throws IOException, DocumentException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new ParserHTML().createPdf(DEST);
}
}
模板 hero.html
<p><span style="font-size:12.0pt; font-family:MS Mincho; color:red">長空abc</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(Broken Sword),</span>
<span style="font-size:12.0pt; font-family:MS Mincho">秦王殘劍</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(Flying Snow),</span>
<span style="font-size:12.0pt; font-family:MS Mincho">飛雪</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(Moon), </span>
<span style="font-size:12.0pt; font-family:MS Mincho">如月</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(the King), and</span>
<span style="font-size:12.0pt; font-family:MS Mincho">秦王</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(Sky).</span></p>
相關文章
- Ubuntu中解決pdf中文亂碼或不顯問題Ubuntu
- iText操作PDF問題總結
- DotNetZip解決檔名稱中文字元不顯示的問題字元
- LINUX SSH顯示中文亂碼問題解決Linux
- JSP顯示中文問題的解決方案(轉)JS
- LiveCharts中文顯示亂碼問題的解決Echarts
- 解決WordPress文章上傳圖片使用中文名不顯示的問題
- iText中文,報錯解決
- JIVE在WINDOWS下的中文顯示問題的解決Windows
- vue-解決background-image:url不顯示問題Vue
- 解決MySQL中文亂碼和插入中文不顯示的方法MySql
- ssh三大框架簡單整合,struts2整合JasperReport報表、圖表,解決HTML顯示圖片不出來,PDF中文不顯示的問題框架HTML
- 三種方法教你解決輸入法不顯示問題
- 解決arcgis for android中feature不顯示的問題Android
- navicat 表中文顯示? 解決
- Java 解決中文亂碼問題Java
- Win10系統pdf縮圖不顯示的解決方法Win10
- java-pdf-itext7、itextpdf 生成pdf 文件Java
- ubuntu 中文顯示亂碼問題Ubuntu
- WordPress中文標題無法顯示的解決方法
- 解決SecureCRT中文顯示亂碼Securecrt
- QT中文顯示亂碼解決QT
- 解決 PBootCMS 後臺登入不顯示驗證碼的問題boot
- 解決CentOS 中顯示亂碼問題CentOS
- Java操作PDF檔案之ITextJava
- 解決國外模板h1、h2、h3…不顯示中文文章標題的問題
- 徹底解決pidgin群顯示null問題及無法輸入中文的問題Null
- 全面解決amule容易崩潰和中文顯示、輸入的問題(轉)
- 修改java或css後不生效,還是顯示修改之前的樣式,問題已解決JavaCSS
- Blazor 部署 pdf.js 不能正確顯示中文資源解決辦法BlazorJS
- Navicat for mysql 顯示中文亂碼問題MySql
- pyplot latex顯示中文出錯問題
- 解決windows上靜態連結cairo不顯示東西的問題WindowsAI
- Python詞雲庫wordcloud中文顯示問題詳解PythonCloud
- 如何解決python 圖表中文顯示亂碼問題Python
- pyecharts地圖功能,並解決顯示不全或只顯示南海諸島問題解決Echarts地圖
- java中解決request中文亂碼問題Java
- vmware不顯示usb圖示解決辦法