自定义富文本编辑器分为前端项目和后端项目两个部分,首先先说一下前端项目

前端

前端项目地址: https://github.com/haoxiaoyong1014/editor-ui

编辑器名称: tinymce

前端采用的 vue.js

至于Vue 中怎么集成 tinymce 编辑器参考: https://segmentfault.com/a/1190000012791569

其中关键代码在项目中的 index.vue

<template>
<div><Row><Col span="18" offset="3"><Card shadow><Upload action="http://localhost:2020/upload/word/template":on-success="handleSuccess"><Button icon="ios-cloud-upload-outline">上传模板</Button></Upload><Form ref="editorModel" :model="editorModel" :rules="editorRules"><FormItem prop="content"><textarea  class='tinymce-textarea' id="tinymceEditer" style="height: 800px"></textarea></FormItem><FormItem><Button type="primary" @click="handleSubmit('editorModel')">Submit</Button><Button type="ghost" @click="handleReset('editorModel')">Reset</Button></FormItem></Form><Spin fix v-if="spinShow"><Icon type="load-c" size=18 class="demo-spin-icon-load"></Icon><div>加载组件中...</div></Spin></Card></Col></Row>
</div>
</template>
<script>
import tinymce from 'tinymce';
import util from '@/libs/util';
export default {name: 'index',data () {return {spinShow: true,editorModel: {content: 'dfsd'},content2: 'sdds',editorRules: {content: [{type: 'string',min: 5,message: 'the username size shall be no less than 5 chars ',trigger: 'blur'}]},customEditor: null};},methods: {handleSuccess(res){console.log(res)this.customEditor=res.content;console.log('haoxy'+this.customEditor)tinymce.get('tinymceEditer').setContent(this.customEditor);/*this.$nextTick(() => {this.customEditor = tinymce.get("tinymceEditer");})*/},init () {this.$nextTick(() => {let vm = this;let height = document.body.offsetHeight - 300;tinymce.init({selector: '#tinymceEditer',branding: false,elementpath: false,height: height,language: 'zh_CN.GB2312',menubar: 'edit insert view format table tools',plugins: ['advlist autolink lists link image charmap print preview hr anchor pagebreak imagetools','searchreplace visualblocks visualchars code fullpage','insertdatetime media nonbreaking save table contextmenu directionality','emoticons paste textcolor colorpicker textpattern imagetools codesample'],toolbar1: ' newnote print preview | undo redo | insert | styleselect | forecolor backcolor bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image emoticons media codesample',autosave_interval: '20s',image_advtab: true,table_default_styles: {width: '100%',height: '100%',borderCollapse: 'collapse'},setup: function (editor) {editor.on('init', function (e) {vm.spinShow = false;if (localStorage.editorContent) {tinymce.get('tinymceEditer').setContent(localStorage.editorContent);}});editor.on('keydown', function (e) {localStorage.editorContent = tinymce.get('tinymceEditer').getContent();vm.editorModel.content = tinymce.get('tinymceEditer').getContent();});}});/*this.customEditor = tinymce.get("tinymceEditer");*/});},handleSubmit (name) {this.$refs[name].validate((valid) => {if (valid) {util.post('/html/pdf', this.editorModel).then(res => {this.$Message.success('Success!');});} else {this.$Message.error('Fail!');}});},handleReset (name) {this.$refs[name].resetFields();},},mounted () {this.init();},destroyed () {tinymce.get('tinymceEditer').destroy();}
}
</script>

在原有的编辑器的基础上新增了上传模板功能, 在上传成功之后拿到服务端 返回的 html 数据,将其设置到

<textarea class='tinymce-textarea' id="tinymceEditer" style="height: 800px"></textarea>
这个标签中,所有的编辑器都是这个道理.

上传成功之后:

handleSuccess(res){console.log(res)this.customEditor=res.content;console.log('haoxy'+this.customEditor)tinymce.get('tinymceEditer').setContent(this.customEditor);

看下效果图:

点击 submit 我是在后端将其转换成了 pdf 文件(按需求定义)

如果在集成中出现: Uncaught SyntaxError: Unexpected token < 这个错误

解决方法:

在 tinymce.init 中把language : zh_CN.GB2312 去掉

在你需要的地方引入: import '../../../zh_CN'(我是把 zh_CN.js放到了根目录下了,效果是一样的),

如果编辑器的样式还是没有出来,只出来一个编辑框的话 ,就在你的根目录下的 index.html 中引入:

<script src="https://cdn.bootcss.com/tinymce/4.7.4/tinymce.min.js"></script>

后端

后端(服务端)项目地址: https://github.com/haoxiaoyong1014/editor-service

后端采用: springBoot , POI

这里就不对POI做过多的说明了,贴个官网 https://poi.apache.org/,随意看看。

整体思路:

1,在编辑器原来的基础上增加上传模板按钮

2, 前端上传 word 模板

3, 服务端接收将 word 转换为html 返回前端

4, 前端拿到服务端返回的值,将其放到富文本编辑器中

后端主要是第3步

首先搞清楚下要将doc/docx文档转成html/htm的话要怎么处理,根据POI的文档,我们可以知道,处理doc 格式文件对应的 POI API 为 HWPF、docx 格式为 XWPF。此处参考下这篇好文:http://www.open-open.com/lib/view/open1389594797523.html 在格式转换上说得很清楚。

所以整体就是:根据文档类型,doc我们用HWPF对象处理转换、docx用XWPF对象处理转换。

顺便贴一下这个在线文档 http://poi.apache.org/apidocs/index.html,不得不说看得相当麻烦,特别是XWPF的。

所需依赖

<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.12</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.12</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.document</artifactId><version>1.0.5</version></dependency><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>org.apache.poi.xwpf.converter.xhtml</artifactId><version>1.0.5</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.commons.io/commonsIO --><dependency><groupId>org.apache.commons.io</groupId><artifactId>commonsIO</artifactId><version>2.6</version></dependency><dependency><groupId>com.aspose.words</groupId><artifactId>aspose-words</artifactId><version>15.8.0</version></dependency>

其中 commonsIO 这个依赖不知道为什么下载不下来,我将 jar 放到了我的私服上,在pom.xml 中有体现,这里不做详细说明

一、处理doc。

这个相对简单,网上一查一堆,我的代码也是根据网上的做下自己的优化和逻辑。

因为POI很早前就可以支持doc的处理,所以资料比较多。

思路就是:HWPFDocument对象实例化文件流 -> WordToHtmlConverter对象处理HWPFDocument对象及预处理页面的图片等(主要是图片)

文档说明是:

Converts Word files (95-2007) into HTML files.
This implementation doesn’t create images or links to them. This can be changed by overriding AbstractWordConverter.processImage(Element, boolean, Picture) method.

-> org.w3c.dom.Document对象处理WordToHtmlConverter,生成DOM对象 -> 输出文件。

这里有个好处就是使用到了Document对象,从而解决了编码、文件格式等问题。

这里因为过程简单,直接贴简单demo,看注释即可:

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;import org.apache.commons.io.FileUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.core.FileURIResolver;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.w3c.dom.Document;public class POIForeViewUtil {public void parseDocx2Html() throws Throwable {final String path = "/tmp/";final String file = "xxxxxxx.doc";InputStream input = new FileInputStream(path + file);String suffix = file.substring(file.indexOf(".")+1);// //截取文件格式名//实例化WordToHtmlConverter,为图片等资源文件做准备WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());wordToHtmlConverter.setPicturesManager(new PicturesManager() {public String savePicture(byte[] content, PictureType pictureType,String suggestedName, float widthInches, float heightInches) {return suggestedName;}});if ("doc".equals(suffix.toLowerCase())) {// docHWPFDocument wordDocument = new HWPFDocument(input);wordToHtmlConverter.processDocument(wordDocument);//处理图片,会在同目录下生成并保存图片List pics = wordDocument.getPicturesTable().getAllPictures();if (pics != null) {for (int i = 0; i < pics.size(); i++) {Picture pic = (Picture) pics.get(i);try {pic.writeImageContent(new FileOutputStream(path+ pic.suggestFullFileName()));} catch (FileNotFoundException e) {e.printStackTrace();}}}} // 转换Document htmlDocument = wordToHtmlConverter.getDocument();ByteArrayOutputStream outStream = new ByteArrayOutputStream();DOMSource domSource = new DOMSource(htmlDocument);StreamResult streamResult = new StreamResult(outStream);TransformerFactory tf = TransformerFactory.newInstance();Transformer serializer = tf.newTransformer();serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");//编码格式serializer.setOutputProperty(OutputKeys.INDENT, "yes");//是否用空白分割serializer.setOutputProperty(OutputKeys.METHOD, "html");//输出类型serializer.transform(domSource, streamResult);outStream.close();String content = new String(outStream.toByteArray());//我此时不想让它生成文件,所以我注释掉了,按需求定/*FileUtils.writeStringToFile(new File(path, "interface.html"), content,"utf-8");*/}public static void main(String[] args) throws Throwable {new POIForeViewUtil().parseDocx2Html();}
}

其中 content 就是我们想要的 HTML 数据

接下来我看第二中 docx

二、处理docx。

docx是07的版本,处理起来困难的多,貌似POI对docx的处理方法没有doc那么便捷,处理样式等等都有问题,我遇到的两个最明显问题就是字体编码问题和表格的边框线显示。

思路:XWPFDocument加载文件流 -> XHTMLOptions处理页面资源(主要图片) -> OutputStream输出流直接输出文件。

过程代码相当简单,可是越简单结果约没有预期的好。输出的文件字体编码默认为GBK,例如我的“微软雅黑”字体就变成“寰蒋闆呴粦”,而且节点的显示也没有doc处理的好。

同样贴一下demo代码:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.core.FileURIResolver;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;public class Word07ToHtml {public static void parseToHtml() throws IOException {File f = new File("tmp/xxxxx.docx");if (!f.exists()) {System.out.println("Sorry File does not Exists!");} else {if (f.getName().endsWith(".docx") || f.getName().endsWith(".DOCX")) {// 1) 加载XWPFDocument及文件InputStream in = new FileInputStream(f);XWPFDocument document = new XWPFDocument(in);// 2) 实例化XHTML内容(这里将会把图片等文件放到生成的"word/media"目录)File imageFolderFile = new File("f:/opt");XHTMLOptions options = XHTMLOptions.create().URIResolver(new FileURIResolver(imageFolderFile));options.setExtractor(new FileImageExtractor(imageFolderFile));//options.setIgnoreStylesIfUnused(false);//options.setFragment(true);// 3) 将XWPFDocument转成XHTML并生成文件  --> 我此时不想让它生成文件,所以我注释掉了,按需求定/*OutputStream out = new FileOutputStream(new File(path, "result.html"));XHTMLConverter.getInstance().convert(document, out, null);*/ByteArrayOutputStream baos = new ByteArrayOutputStream();XHTMLConverter.getInstance().convert(document, baos, options);String content = baos.toString();baos.close();} else {System.out.println("Enter only MS Office 2007+ files");}}}
}

其中 content 就是我们想要的 HTML 数据

点击 submit 我是在后端将其转换成了 pdf 文件(按需求定义)

POI的jar包下载路径:https://archive.apache.org/dist/poi/release/bin/poi-bin-3.9-20121203.zip

至此 富文本编辑器增加导入 word 模板就结束了, 无论是导入文件还导入图片都是一个道理.

注: 前端项目使用方式

git clone https://github.com/haoxiaoyong1014/editor-ui.git

进入项目执行:

npm install

npm run dev

前提: 需要安装 npm

前端项目地址: https://github.com/haoxiaoyong1014/editor-ui

后端项目地址: https://github.com/haoxiaoyong1014/editor-service

如果对您有帮助还请给个星星哦!

2018/10/19更新,更新内容修复 bug

放到项目中遇到的问题修复

  • 问题描述1:

当上传模板之后点击浏览器刷新编辑框中的内容会变为之前上传的内容

  • 解决方法:
if (localStorage.editorContent) {tinymce.get('tinymceEditer').setContent(localStorage.editorContent);}

将这段代码注释掉即可,因为编辑器会自动的将内容保存到本地,当你去点击浏览器刷新的时候他会去本地取出并赋值到编辑框中

  • 问题描述2:

当你在编辑框中进行编辑的时候tinymce编辑器监听了键盘按下的事件,但是键盘按下的前一个字符没有保存,例如:

你在编辑框中输入4个字符 aaaa 你再点击submit生成pdf文件,但是 pdf文件中就只有3个字符aaa

  • 解决方法:

因为编辑器只监听了keydown事件,并没有去监听keyup事件
所以加上如下代码即可

editor.on('keyup', function (e) {localStorage.editorContent = tinymce.get('tinymceEditer').getContent();vm.editorModel.content = tinymce.get('tinymceEditer').getContent();});
  • 问题描述3:

当点击submit 生成pdf文件时,生成的 pdf 文件样式改变了

  • 解决方法:

这是因为将 word 文档转换成 html 的时候自动的加上了这段样式

<div style="width: 595.0pt; margin: 72.0pt 90.0pt 72.0pt 90.0pt;"></div>

解决方法可以在前端解决也可以在后端去解决,这里我选择了在后端解决

后端在返回给前端html 的时候,在返回的内容上加上

respInfo.setContent("<div style=\"width: 595.0pt; margin: -72.0pt -90.0pt -72.0pt -90.0pt !important;\">"+content+"</div>")

总结何尝不是一种学习

Vue 自定义富文本编辑器 tinymce 支持导入 word 模板相关推荐

  1. 富文本编辑器tinymce支持从word复制粘贴保留格式和图片的插件powerpaste

    公司做的项目需要用到粘贴Word功能.就是将word内容一键粘贴到网页编辑器(在线富文本编辑器)中.Chrome+IE默认支持粘贴剪切板中的图片,但是我要粘贴的文章存在word里面,图片多达数十张,我 ...

  2. 【富文本编辑器功能】vue实现富文本编辑器Tinymce功能,保留编辑器格式文章展示在页面上【前后端代码展示,简单好用】

    前言: 这个Tinymce富文本编辑器是vue-element-admin内集成好的,使用过后体验非常不错,很简单易用.这里分享一下,同时又看到了网上帖子都没什么人写前后端同时展示的,很多人想知道编辑 ...

  3. vue整合富文本编辑器tinymce

    一.复制文本编辑器组件到项目文件夹里面 二.在build下的webpack.dev.conf.js里面添加 templateParameters: {BASE_URL: config.dev.asse ...

  4. 富文本编辑器tinymce 自定义中文字号(四号,小四,五号,小五等)

    富文本编辑器tinymce 自定义中文字号(四号,小四,五号,小五等) 前因 探索 最终解决 最终效果 关键代码 前因 在写富文本编辑器转换word的过程中,因为所使用的富文本编辑器tinymce中的 ...

  5. vue+summernote富文本编辑器

    vue+summernote富文本编辑器 最近项目中有新增编辑报告的需求需使用富文本编辑器,在网上找了几篇相关博客,于是选择了summernote ,summernote是一款轻量级的富文本编辑器,比 ...

  6. vue项目+富文本编辑器ueditor - 资源篇

    资源地址: git源码 · 解说地址 git源码:源码下载地址 · [基于 vue-cli 2.x 的完整 DEMO] ueditor插件Demo演示地址 说明: 支持 vue-cli 2.x 支持 ...

  7. 使用vue的富文本编辑器操作

    使用vue的富文本编辑器操作 vue的富文本编辑器使用以及多图片文件上传与回显 一. vue-quill-edit 1. 安装vue的富文本 cd 当前的vue项目路径 npm install qui ...

  8. UEditor +数学公式+ Vue+ Kityformula 富文本编辑器嵌入数学公式的实现

    UEditor +数学公式+ Vue + Kityformula 富文本编辑器嵌入数学公式的实现 首先展示一下代码实现后的效果: 现在我们开始写代码 第一步:我们需要去下载Ueditor官方的包:Ue ...

  9. html编辑保存为word文档,html 保存成word (富文本编辑器导出内容成word)

    这几天项目里有个需求,用到富文本编辑器,然后导出word. 富文本编辑器,网上很多,使用夜很简单,我们使用的是kindEditor.百度的ueditor很好,而且文档很全.阿里的kissy 感觉比较复 ...

最新文章

  1. CIE-LUV是什么颜色特征
  2. 心得体悟帖---17、于迷茫低落处找到本心
  3. [delphi]修改indy源码后重新编译
  4. weblogic修改banner_WeblogicScanV1.3
  5. 基于FPGA实现AD7609接口
  6. [华为机试练习题]37.合唱队
  7. 【C++ Primer】第十三章 类继承
  8. 20190803:栈实践(最小栈)
  9. OO’s Sequence
  10. Hyperledger Fabric on SAP Cloud Platform
  11. 【语音加密】基于matlab语音加密【含Matlab源码 1303期】
  12. OpenCV与机器视觉
  13. java源代码反编译_XJad(Java源程序反编译软件)
  14. JAVA基础篇——JAVA运行环境(JDK、JRE、JVM)
  15. 宁皓网bootstrap
  16. 不同局域网下共享打印机的解决思路(保证可用)
  17. 拼一个自己的操作系统(SnailOS 0.03的实现)
  18. Excel 中如何去掉数值中出现的 E +,网上的方法都试过了不管用,改变单元格格式等都无效
  19. jQuery网格插件 ParamQuery
  20. 从keras看VGG16结构图

热门文章

  1. jmf608硬盘修复_JMF608固态硬盘主控 SSD套料 SSD电路板 SATA3 封装BGA152|TSOP48
  2. Win10、Win7系统,电脑蓝屏,什么原因怎么解决?一篇文章彻底解决!
  3. 开源项目推荐:OpenGL/Vulkan/Cairo/Skia/angle/VTK/OpenVG/MyPaint/GIMP/Krita/Pencil2D/inkspace/enve等绘图库或画图软件
  4. PACS—医学影像信息化的基础
  5. Unity3d开发MOBA游戏类《王者荣耀》记录(起)
  6. 在电脑上怎么做判断题打√或x_电脑基础知识竞赛试题
  7. 蓝牙也宽带 诺基亚3230蓝牙共享宽带教程(内网用户设置或网关无响应的解决)
  8. 胶体金纳米颗粒粒径为20~80 nm齐岳生物提供单分散,小粒径及不同粒径大小的金纳米粒子AuNPs
  9. Calcite优化规则之ProjectAggregateMergeRule
  10. Android视频播放器ExoPlayer