IText 导出PDF 中文问题解决

本文介绍了一个使用IText库导出包含中文内容的PDF时遇到的问题及其解决方案。通过引入必要的依赖,如itext-asian和设置正确的字符编码,解决了PDF中文乱码的问题。同时,代码示例展示了如何将HTML转换为PDF并处理中文显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
使用的jar包用maven导入依赖
<!--PDF-->
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itextpdf</artifactId>
  <version>5.4.2</version>
</dependency>
<dependency>
  <groupId>com.itextpdf.tool</groupId>
  <artifactId>xmlworker</artifactId>
  <version>5.4.1</version>
</dependency>
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itext-asian</artifactId>
  <version>5.2.0</version>
</dependency>
<dependency>
  <groupId>org.xhtmlrenderer</groupId>
  <artifactId>flying-saucer-pdf</artifactId>
  <version>9.0.3</version>
</dependency>
<!--PDF-->
/**
     * 导出为 PDF
     *
     * @param
     * @return
     * @throws BusinessException
     */
    public static String specialExportPDF(String moduleName, String fileName, Map<String, String> dataMap) throws BusinessException {
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");

        try {
            //dataMap 要填入模本的数据文件
            //设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,
            //这里我们的模板是放在template包下面
            configuration.setDirectoryForTemplateLoading(new File(FileUtil.getWebRootPath() + "template//import//" + moduleName));
            Template t = null;
            try {
                //.ftl为要装载的模板
                t = configuration.getTemplate(fileName + ".ftl");
            } catch (IOException e) {
                e.printStackTrace();
            }
            fileName = fileName + DateUtil.datetimeToNoSplashString(DateUtil.now()) + ".html";
            String outputFilePath = getOutputXlsTempFilePath(fileName);
            Writer out = null;
            FileOutputStream fos = null;
            try {
                {
                    //输出文档路径及名称
                    fos = new FileOutputStream(outputFilePath);
                    OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
                    //这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。
                    //out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
                    out = new BufferedWriter(oWriter);
                    t.process(dataMap, out);
                    String html = readString(outputFilePath);
                    //创建pdf
                    ItextUtil.createPdf(html,outputFilePath);
                    out.flush();
                    out.close();
                    fos.close();
                    //删除html文件
                   File file = new File(outputFilePath);
                   file.delete();
                }
            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
            } catch (TemplateException e1) {
                e1.printStackTrace();
            }
            //4.返回word文件的下载地址
            return getDownloadXlsTempFileUrl(fileName.replace("html","pdf"));
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 读取文件转换为字符串
     * @param FilePath
     * @return
     */
    private static String readString(String FilePath){
        if(PubUtil.isEmpty(FilePath))return "";
        int len=0;
        StringBuffer str=new StringBuffer("");
        File file=new File(FilePath);
        try {

            FileInputStream is=new FileInputStream(file);
            BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
            String line=null;
            while( (line=in.readLine())!=null ){
                if(len != 0) {// 处理换行符的问题
                    str.append("\r\n"+line);
                }else{
                    str.append(line);
                }
                len++;
            }
            in.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str.toString();
    }
/** PDF生成工具 **/
package com.etom.ebihm.utils;


import com.itextpdf.text.*;
//import com.itextpdf.text.html.simpleparser.HTMLWorker;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.tool.xml.ElementList;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.css.CssFile;
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver;


import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.ElementHandlerPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.itextpdf.text.html.simpleparser.StyleSheet;
import com.itextpdf.text.pdf.PdfWriter;
//import com.lowagie.text.html.simpleparser.HTMLWorker;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.*;
import java.util.List;
//import java.util.ArrayList;

/**
 * 生成PDF工具类
 * Created by Administrator on 2017/8/21.
 */
public class ItextUtil {
//这里的html是将html转化为字符串,非html文件路径
    public static void createPdf(String html,String outPath) {
        ItextUtil ih = new ItextUtil();
        ih.htmlCodeComeFromFile(html,outPath.replace("html","pdf"));
    }
    public void htmlCodeComeFromFile(String html, String pdfPath) {
        Document document = new Document();
        try {
            /*StyleSheet st = new StyleSheet();
            st.loadTagStyle("body", "leading", "16,0");*/
            PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
            document.open();
            Paragraph context = new Paragraph( );
            ElementList elementList = parseToElementList(html, null);
            // 解决中文问题
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            Font FontChinese = new Font(bfChinese, 12, Font.NORMAL);
            context.setFont(FontChinese);
            for (com.itextpdf.text.Element element1 : elementList) {
                context.add(element1);
            }
            document.add(context);
            document.close();
            System.out.println("文档创建成功");
        }catch(Exception e) {
            e.printStackTrace();
        }
    }

    public   ElementList parseToElementList(String html, String css) throws IOException {
        // CSS
        CSSResolver cssResolver = new StyleAttrCSSResolver();
        if (css != null) {
            CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream(css.getBytes()));
            cssResolver.addCss(cssFile);
        }
        // HTML
        MyXMLWorkerHelper.MyFontsProvider fontProvider = new MyXMLWorkerHelper.MyFontsProvider();
        CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
        htmlContext.autoBookmark(false);

        // Pipelines
        ElementList elements = new ElementList();
        ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null);
        HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, end);
        CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline);

        // XML Worker
        XMLWorker worker = new XMLWorker(cssPipeline, true);
        XMLParser p = new XMLParser(worker);
        p.parse(new ByteArrayInputStream(html.getBytes()));

        return elements;
    }
}



/**  重写XMLWorkerHelper类,使用自定义字体    **/
package com.etom.ebihm.utils;

import com.etom.framework.constant.SystemConstants;
import com.etom.framework.utils.FileUtil;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;

import java.io.File;

/**
 * Created by Administrator on 2017/8/21.
 */
public class MyXMLWorkerHelper {
    public static class MyFontsProvider extends XMLWorkerFontProvider {
        public MyFontsProvider() {
            super(null, null);
        }

        @Override
        public Font getFont(final String fontname, String encoding, float size, final int style) {

            String fntname = fontname;
            if (fntname == null) {
                fntname = "宋体";
            }
            Font font = new Font();
            String font_cn = getChineseFont();
            BaseFont bf;
            try {
                bf = BaseFont.createFont(font_cn+",1", //注意这里有一个,1
                        BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                font = new Font(bf,12);
                font.setFamily("SYMBOL");
            }catch (Exception e){
                e.printStackTrace();
            }
            //return super.getFont(fntname, encoding, size, style);
            return font;
        }
    }
    /**
     * 获取中文字体位置
     * @return
     *  @author xxj 2017年4月28日
     */
    private static String getChineseFont(){
        //宋体(对应css中的 属性 font-family: SimSun; /*宋体*/)
       /* String font1 ="C:/Windows/Fonts/simsun.ttc";


        //判断系统类型,加载字体文件
        java.util.Properties prop = System.getProperties();
        String osName = prop.getProperty("os.name").toLowerCase();
        System.out.println(osName);*/
        //File  file = new File(FileUtil.getRealPath(SystemConstants.PATH_PRE_WEBROOT+"://res/font/simsun.ttc"));
        /*if (osName.indexOf("linux")>-1) {
            font1="/usr/share/fonts/simsun.ttc";
        }
        if(!new File(font1).exists()){
            throw new RuntimeException("字体文件不存在,影响导出pdf中文显示!"+font1);
        }*/
	//linux服务器中未安装字体,故在项目资源中传了字体,获取项目字体即可
        File  file = new File(FileUtil.getRealPath(SystemConstants.PATH_PRE_WEBROOT+"://res/font/simsun.ttc"));
        String font1 =FileUtil.getRealPath(SystemConstants.PATH_PRE_WEBROOT+"://res/font/simsun.ttc");
        if(!file.exists()){
            throw new RuntimeException("字体文件不存在,影响导出pdf中文显示!"+font1);
        }
        return font1;
    }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值