前因后果
说说我做的一些努力
- 考虑给百度编辑器开发的一个二次插件,等下会进行说明如何使用改源码的方式开发二次插件
- 后端增加接口,接受word文档,转为html返回前台,前台再根据html内容对于富文本编辑框继续赋值和一些处理
然而,理想很美好,现实很骨感:
- 无法达到100%还原,word里面转译html会存在各种问题
- 有存在无法解析和翻译的部分
- 客户不会买账!(核心原因)
如何解决word转译到富文本编辑的问题
这两天搜索了几乎所有的富文本编辑器(国内用的比较多的)似乎都没有解决这个问题。
然后几乎所有的带word导入粘贴的,几乎都是商业收费软件(还很贵)
无奈之下,BOSS决定掏钱升级ewebeditor
并且怪为什么没有提早说百度编辑器实现不了。(经理&我:???)
所以最后结果就是:我瞎忙活了几天(内心一万个草泥马)。
既然知道了结果为什么还要写这篇文章,我其实很不甘心,一个方案被否决,我决定记录一下这个也许可行的数据方案。
JAVA&百度编辑器实现word粘贴(非完美)
不扯那么多,直接上菜:
1. 前端为百度编辑器自定义一个上传word的功能
- 搜索一下:
UE.commands["setbordervisible"] = {
在它的下面加入如下的代码:
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
| UE.commands["getword"] = { execCommand: function (Name) { if (window.FileReader) { var inputObj=document.createElement('input') inputObj.setAttribute('id','my_inputObj'); inputObj.setAttribute('type','file'); // inputObj.setAttribute('accept','application/msword'); inputObj.setAttribute("style",'visibility:hidden'); document.body.appendChild(inputObj);
inputObj.onchange = function(){ //拿取上传的文档 var fileData = inputObj.files[0]
if(fileData.type.indexOf('word')>-1){ if(fileData.size>1048576){ //控制在1M以内 alert('您上传的文件大于1MB,请上传1MB以内的word文件') return; } console.log(fileData)
}else{ alert('请选择一个word文件') }
} inputObj.click();
} } };
|
增加一个命令叫做:getword
模拟一个input file
,并且模拟一次点击文件上传
如果上传了具体文件,触发onchange
,并且进行word的各种判断
然后将文件的内容传到后台的接口(具体怎么做根据自己的语言来处理)
加入自定义的命令:getword
1 2 3 4 5 6 7 8
| //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起 var btnCmds = ['undo', 'redo', 'formatmatch', 'bold', 'italic', 'underline', 'fontborder', 'touppercase', 'tolowercase', 'strikethrough', 'subscript', 'superscript', 'source', 'indent', 'outdent', 'blockquote', 'pasteplain', 'pagebreak', 'selectall', 'print','horizontal', 'removeformat', 'time', 'date', 'unlink', 'insertparagraphbeforetable', 'insertrow', 'insertcol', 'mergeright', 'mergedown', 'deleterow', 'deletecol', 'splittorows', 'splittocols', 'splittocells', 'mergecells', 'deletetable', 'drafts','getword'];
|
注意到最后一个getword
了么,这就是刚刚加进去的
- 在
Lang/zh-cn/zh-cn.js
文件当中,增加按钮说明,直接照着截图加就行
为了防止图裂,还是写一下,搜一下``scrawl:’涂鸦’`,基本可以找到大概的位置
- 修改
ueditor.config.js
文件,增加新的按钮
在help
的后面加一个getword
就好了,注意以下json格式,逗号不能少
- 增加样式,修改
Themes/default/ueditor.css
,直接在最底下增加
1 2 3 4 5 6 7 8
| .edui-default .edui-toolbar .edui-for-getword .edui-icon { background-image: url(../images/wordT1.png); background-repeat: no-repeat; width: 20px !important; background-size: 18px; background-position: center; }
|
Tip:wordT1.png 是一个word的小图标,这里就不提供了
才怪:Themes/default/images/wordT1.png
https://gitee.com/lazyTimes/imageReposity/raw/master/img/wordT1.png
上面这一套做完之后,基本上在百度编辑器里面会多出一个图标,接下来需要后端开发接口,对接这个插件的行为和操作
2. 后端为word文件做转化为html的操作,然后将html原文返回给前端
做这个接口要特别的小心,需要防止接口被滥用,拖垮服务器资源,因为转化和图片存储的代价还是不小的,需要控制可以转化的大小
前文也说了,老板都出钱升级了,我还玩你个鬼的百度编辑器,溜了溜了,用ewebeidor
,下面是网上搜下来的一个word转html的工具方法,需要apach-poi
的支持,我用的是3.12
版本,具体的内容看自己。
注意以下:docx 和 doc 在poi里面是需要用不同的对象进行操作的,后续自己也会补一补这一块的内容
poi 还是挺强的,很牛逼,把巨硬的那一套治的服服帖帖
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
| 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.extractor.WordExtractor; import org.apache.poi.hwpf.model.PAPX; import org.apache.poi.hwpf.usermodel.Picture; import org.apache.poi.hwpf.usermodel.PictureType; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFNumbering; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering; import org.w3c.dom.Document;
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 java.io.*; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List;
/** * 根据poi写的word帮助类 * @Date 2020/10/12 18:26 **/ public class WordHelper {
public static void parseDocx2Html() throws Throwable { final String path = "D:\\zxd\\mark\\罗湖兼容性\\20201012word导出必备\\"; final String file = "4403080004_深圳盐田政府在线_20200927_11064.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() { @Override public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, float heightInches) { return suggestedName; } }); if ("doc".equals(suffix.toLowerCase())) { // docx HWPFDocument wordDocument = new HWPFDocument(input); wordToHtmlConverter.processDocument(wordDocument); //处理图片,会在同目录下生成 image/media/ 路径并保存图片 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()); System.err.println(content); FileUtils.writeStringToFile(new File(path, "interface.html"), content, "utf-8"); }
public static void main(String[] args) throws Throwable { WordHelper.parseDocx2Html(); }
}
|
后续
滚回去继续升级ewebeditor
了,擦公司的前辈居然有人做了一个一键排版和文章重排,直接动了源代码,有时间研究一下,果然老系统出神仙。
PS:老系统代码里面老板的名字在上面,老板是大公司程序员出身,挺好。
总结:
永远不要小看任何细节的点,看似平平无奇的功能,其实真正考虑要实现的时候。
一个简单的复制粘贴其实也并不简单。word的复制和原样粘贴要实现其实不太容易。
那么这种word转译的exe插件,他们是怎么做到的,我现在产生了无限的思考……