富文本编辑器(html格式文本)导出word和pdf原创
金蝶云社区-丁梦洋
丁梦洋
3人赞赏了该文章 4,127次浏览 未经作者许可,禁止转载编辑于2024年06月20日 21:19:58

客户想要在平台提供的富文本编辑器控件旁边加两按钮实现导出word和pdf,本来想参考这里自带的打印和预览结果是纯前端实现的,操作代码里也没发现相关操作,所以得重新开发...

image.png

思路:

富文本编辑器的内容其实是一段html格式文本,所以本质上是html如何生成word和pdf,和平台没啥关系,百度解决方案就行


实现代码:

导出word很简单,用poi相关类就行,平台也有依赖相关jar包,无需额外添加依赖

RichTextEditor richTextEditor = this.getView().getControl("a2h6_richtexteditorap");
String text = "<html>"+richTextEditor.getText()+"</html>";

byte[] buf = text.getBytes(StandardCharsets.UTF_8);
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buf);
     POIFSFileSystem poifsFileSystem = new POIFSFileSystem();
     ByteArrayOutputStream out = new ByteArrayOutputStream()){
     
    DirectoryEntry directoryEntry = poifsFileSystem.getRoot();
    //固定写死
    directoryEntry.createDocument("WordDocument",byteArrayInputStream);
    poifsFileSystem.writeFilesystem(out);

    //写入临时文件,上传文件服务器
    TempFileCache tempFileCache = CacheFactory.getCommonCacheFactory().getTempFileCache();
    String url = tempFileCache.saveAsUrl("test.doc", out.toByteArray(), 3600);
    this.getView().download(url);
} catch (IOException e) {
    this.getView().showErrorNotification("导出失败:"+e.getMessage());
}


导出pdf用了itext相关类,也无需额外添加依赖,但是坑比较多,主要有:

  • itext默认不支持中文,需要添加对应的中文字体

  • 从富文本编辑器拿到的html文本里面的font-family有些是中文名,客户会从他们的模板里复制别的字体的文本过来,比如彩虹小标宋,彩虹粗仿宋这种字体,富文本编辑器里没有,导致导出的pdf展示异常


这里我们和客户约定了只使用彩虹小标宋,彩虹粗仿宋,宋体这几种字体(字体文件可以去这下载),所以最终代码如下

private Map<String, String> FONT_FAMILY_MAP = new HashMap<String, String>(){{
    put("彩虹小标宋", "chxbs");
    put("彩虹粗仿宋", "chcfs");
    put("宋体", "SimSun");
}};
private void toPdfAndDownload(){
    RichTextEditor richTextEditor = this.getView().getControl("a2h6_richtexteditorap");
    String text = richTextEditor.getText();
    /******处理html********/
    org.jsoup.nodes.Document doc = Jsoup.parse(text);
    //规范html格式,让所有标签都闭合!
    doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml);
    doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml);
    
    //把html里的中文字体名替换成FONT_FAMILY_MAP里的
    for (Element element : doc.getElementsByAttribute("style")) {
        String style = element.attr("style");
        for (Map.Entry<String, String> entry : FONT_FAMILY_MAP.entrySet()) {
            if (style.contains(entry.getKey())){
                element.attr("style",style.replace(entry.getKey(), entry.getValue()));
            }
        }
    }
    String html = doc.html();
    
    /******导出pdf********/
    ITextRenderer renderer = new ITextRenderer();
    renderer.setDocumentFromString(html);
    try (ByteArrayOutputStream out = new ByteArrayOutputStream()){
        //字体支持
        ITextFontResolver fontResolver = renderer.getFontResolver();
        boolean isLinux = "linux".equalsIgnoreCase(System.getProperty("os.name"));
        boolean embedded = isLinux ? BaseFont.EMBEDDED:BaseFont.NOT_EMBEDDED;
        //这里addFont方法第二个参数fontFamilyNameOverride和我们html里的font_family要对应,才能正常适配
        //宋体在苍穹依赖的jar包里有,直接获取
        fontResolver.addFont("jar:"+Thread.currentThread().getContextClassLoader().getResource("simsun.ttc").getPath(),
                "SimSun",BaseFont.IDENTITY_H,embedded,null);
        //彩虹小标宋
        fontResolver.addFont(isLinux? "linux路径/chxbs.ttf":"windows路径/chxbs.ttf",
                "chxbs",BaseFont.IDENTITY_H,embedded,null);
        //彩虹粗仿宋
        fontResolver.addFont(isLinux? "linux路径/chcfs.ttf":"windows路径/chcfs.ttf",
                "chcfs",BaseFont.IDENTITY_H,embedded,null);

        renderer.layout();
        renderer.createPDF(out);
        renderer.finishPDF();

        //写入临时文件,上传文件服务器
        TempFileCache tempFileCache = CacheFactory.getCommonCacheFactory().getTempFileCache();
        String url = tempFileCache.saveAsUrl("test.pdf", out.toByteArray(), 3600);
        this.getView().download(url);
    } catch (Exception e) {
        this.getView().showErrorNotification("导出失败:"+e.getMessage());
    }
}


图标赞 3
3人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!