- 浏览: 169587 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
why240829544:
谢谢
Spring Security 2.0.x中文参考文档.pdf -
lzc879141573:
...
Spring Security 2.0.x中文参考文档.pdf -
zpl:
C:\Documents and Settings\Admin ...
导入word到Fckeditor(java实现) -
zpl:
[img][/img] asdfasdfasdfa
导入word到Fckeditor(java实现) -
zhoutao.temp:
Java文件下载的几种方式
最近项目可以说到达了一个里程碑,借这篇文章把前面的技术进行总结.
我们的项目是给一个政府单位开发的,后台其实是个CMS系统,客户非要完成一个功能就是把WORD直接导入到Web 编辑器中,我们是用的是Fckeditor2.5版本,这个功能让我很头疼,想了几天没有思路,但是忽然看到了网上的一篇文章 地址如下:
3楼的哥们把代码贴了上了,不错的思路。
首先用调用COM组件把Word转为html ,然后通过截取重要的源代码 ,最后把这代码放到fck编辑器中,我在做的中间还遇到了很多技术细节问题,下面来看我的实现
使用jacob 来把word转成html
- /**
- * 把word文件转换成html文件
- *
- * @param src
- * 原文件
- * @param out
- * 目标文件
- */
- public static synchronized void word2Html(String src, String out) {
- ActiveXComponent app = null;
- try {
- app = new ActiveXComponent("Word.Application");// 启动word
- app.setProperty("Visible", new Variant(false));
- // 设置word不可见
- Dispatch docs = app.getProperty("Documents").toDispatch();
- Dispatch doc = Dispatch.invoke(docs, "Open", Dispatch.Method, new Object[] { src, new Variant(false), new Variant(true) }, new int[1]).
- toDispatch();
- // 打开word文件 8转为 html 9转为 mht
- Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object [] {out, new Variant(8) }, new int[1]);
- Variant f = new Variant(false);
- Dispatch.call(doc, "Close", f);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 注意这里一定 要关闭否则服务器端会有很多winword.exe进程
- app.invoke("Quit", new Variant[] {});
- app = null;
- }
- }
/** * 把word文件转换成html文件 * * @param src * 原文件 * @param out * 目标文件 */ public static synchronized void word2Html(String src, String out) { ActiveXComponent app = null; try { app = new ActiveXComponent("Word.Application");// 启动word app.setProperty("Visible", new Variant(false)); // 设置word不可见 Dispatch docs = app.getProperty("Documents").toDispatch(); Dispatch doc = Dispatch.invoke(docs, "Open", Dispatch.Method, new Object[] { src, new Variant(false), new Variant(true) }, new int[1]). toDispatch(); // 打开word文件 8转为 html 9转为 mht Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object [] {out, new Variant(8) }, new int[1]); Variant f = new Variant(false); Dispatch.call(doc, "Close", f); } catch (Exception e) { e.printStackTrace(); } finally { // 注意这里一定 要关闭否则服务器端会有很多winword.exe进程 app.invoke("Quit", new Variant[] {}); app = null; } }
上面的代码其实完成的功能其实就是通过调用COM组件打开word程序然后隐藏窗口然后把打开的word文件另存为html.
2.用Apache的CommonsIO读取文件
- /**
- * 根据文件名读取出html代码
- *
- * @param fileName
- * @return
- */
- public static synchronized String getHtmlCode(String fileName) {
- InputStream in = null;
- String result = null;
- try {
- in = new FileInputStream(fileName);
- result = IOUtils.toString(in, "gb2312");
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- IOUtils.closeQuietly(in);
- }
- return result;
- }
/** * 根据文件名读取出html代码 * * @param fileName * @return */ public static synchronized String getHtmlCode(String fileName) { InputStream in = null; String result = null; try { in = new FileInputStream(fileName); result = IOUtils.toString(in, "gb2312"); } catch (Exception e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(in); } return result; }默认转成的html文件就是gb2312编码的 这里注意你读取出来的字符串必须是包含空格的,意思就是把读取出来的字符串拷出来放到文本文档里面的代码和html的源代码格式完全一样.
3.截取body代码
- /**
- * 截取body内容
- *
- * @param bodyCode
- * @return
- */
- public static synchronized String performBodyCode(String htmlCode) {
- String bodyCode = "";
- // 处理body
- int bodyIndex = htmlCode.indexOf("<body");
- int bodyEndIndex = htmlCode.indexOf("</html>");
- if (bodyIndex != -1 && bodyEndIndex != -1) {
- htmlCode = htmlCode.substring(bodyIndex, bodyEndIndex);
- //bodyCode = StringUtils.replace(htmlCode, "v:imagedata", "img");
- //bodyCode = StringUtils.replace(bodyCode, "</v:imagedata>", "");
- bodyCode=htmlCode;
- }
- htmlCode = null;
- return bodyCode;
- }
/** * 截取body内容 * * @param bodyCode * @return */ public static synchronized String performBodyCode(String htmlCode) { String bodyCode = ""; // 处理body int bodyIndex = htmlCode.indexOf("<body"); int bodyEndIndex = htmlCode.indexOf("</html>"); if (bodyIndex != -1 && bodyEndIndex != -1) { htmlCode = htmlCode.substring(bodyIndex, bodyEndIndex); //bodyCode = StringUtils.replace(htmlCode, "v:imagedata", "img"); //bodyCode = StringUtils.replace(bodyCode, "</v:imagedata>", ""); bodyCode=htmlCode; } htmlCode = null; return bodyCode; }
转成的html代码中很多一部分是无用的代码 我们需要对他进行减肥 已经标签的替换.
4.处理html代码中的style标签
- /**
- * 处理Style标签中的内容
- *
- * @param htmlCode
- * @return
- */
- public static synchronized String performStyleCode(String htmlCode) {
- String result = "";
- int index = 0;
- int styleStartIndex = 0;
- int styleEndIndex = 0;
- // 截取<style>标签中开始部分的坐标
- while (index < htmlCode.length()) {
- int styleIndexStartTemp = htmlCode.indexOf("<style>", index);
- if (styleIndexStartTemp == -1) {
- break;
- }
- int styleContentStartIndex = htmlCode.indexOf("<!--", styleIndexStartTemp);
- if (styleContentStartIndex - styleIndexStartTemp == 9) {
- styleStartIndex = styleIndexStartTemp;
- break;
- }
- index = styleIndexStartTemp + 7;
- }
- // 截取style标签中后面部分的坐标
- index = 0;
- while (index < htmlCode.length()) {
- int styleContentEndIndex = htmlCode.indexOf("-->", index);
- if (styleContentEndIndex == -1) {
- break;
- }
- int styleEndIndexTemp = htmlCode.indexOf("</style>", styleContentEndIndex);
- if (styleEndIndexTemp - styleContentEndIndex == 5) {
- styleEndIndex = styleEndIndexTemp;
- break;
- }
- index = styleContentEndIndex + 4;
- }
- result = htmlCode.substring(styleStartIndex, styleEndIndex + 8);
- return result;
- }
/** * 处理Style标签中的内容 * * @param htmlCode * @return */ public static synchronized String performStyleCode(String htmlCode) { String result = ""; int index = 0; int styleStartIndex = 0; int styleEndIndex = 0; // 截取<style>标签中开始部分的坐标 while (index < htmlCode.length()) { int styleIndexStartTemp = htmlCode.indexOf("<style>", index); if (styleIndexStartTemp == -1) { break; } int styleContentStartIndex = htmlCode.indexOf("<!--", styleIndexStartTemp); if (styleContentStartIndex - styleIndexStartTemp == 9) { styleStartIndex = styleIndexStartTemp; break; } index = styleIndexStartTemp + 7; } // 截取style标签中后面部分的坐标 index = 0; while (index < htmlCode.length()) { int styleContentEndIndex = htmlCode.indexOf("-->", index); if (styleContentEndIndex == -1) { break; } int styleEndIndexTemp = htmlCode.indexOf("</style>", styleContentEndIndex); if (styleEndIndexTemp - styleContentEndIndex == 5) { styleEndIndex = styleEndIndexTemp; break; } index = styleContentEndIndex + 4; } result = htmlCode.substring(styleStartIndex, styleEndIndex + 8); return result; }
word转为html后里面有很多的style标签 其中
<style>
<!--- 内容省略
--->
<style>
类似于如上带html注释的style标签才是有用的 其余全是无用的.上面的代码就是把这有用的代码截取出来.如果你在第2部的时候格式读取正确,那么上面的代码截取出来的代码肯定没问题.
5.处理word文件中的图片
- /**
- * 处理body中的图片内容
- * @param bodyContent
- * @return
- */
- public static synchronized String performBodyImg(String bodyContent) {
- //根据图片名称预览图片action的地址
- String newImgSrc = "tumbnail.action?fileName=";
- //存放word文件的物理位置
- String filePath = ResourceBundle.getBundle("sysConfig").getString("userFilePath.word");
- //存放图片的物理位置
- String imgPath = ResourceBundle.getBundle("sysConfig").getString("userFilePath.image");
- Parser parser = Parser.createParser(bodyContent, "gb2312");
- ImgTagVisitor imgTag = new ImgTagVisitor();
- try {
- parser.visitAllNodesWith(imgTag);
- // 得到所有图片地址
- List<String> imgUrls = imgTag.getSrcStringList();
- for (String url : imgUrls) {
- String uuid = UUID.randomUUID().toString();
- String extName = url.substring(url.lastIndexOf("."));
- String newImgFileName = newImgSrc + uuid + extName;
- bodyContent = StringUtils.replace(bodyContent, url, newImgFileName);
- bodyContent = StringUtils.replace(bodyContent, url, newImgFileName);
- ImageUtils.copy(filePath + url, imgPath + uuid + extName);
- }
- } catch (ParserException e) {
- e.printStackTrace();
- }
- String result = bodyContent;
- //去除多余的代码
- result = StringUtils.replace(result, "<![endif]>", "");
- result = StringUtils.replace(result, "<![if !vml]>", "");
- bodyContent = null;
- return result;
- }
/** * 处理body中的图片内容 * @param bodyContent * @return */ public static synchronized String performBodyImg(String bodyContent) { //根据图片名称预览图片action的地址 String newImgSrc = "tumbnail.action?fileName="; //存放word文件的物理位置 String filePath = ResourceBundle.getBundle("sysConfig").getString("userFilePath.word"); //存放图片的物理位置 String imgPath = ResourceBundle.getBundle("sysConfig").getString("userFilePath.image"); Parser parser = Parser.createParser(bodyContent, "gb2312"); ImgTagVisitor imgTag = new ImgTagVisitor(); try { parser.visitAllNodesWith(imgTag); // 得到所有图片地址 List<String> imgUrls = imgTag.getSrcStringList(); for (String url : imgUrls) { String uuid = UUID.randomUUID().toString(); String extName = url.substring(url.lastIndexOf(".")); String newImgFileName = newImgSrc + uuid + extName; bodyContent = StringUtils.replace(bodyContent, url, newImgFileName); bodyContent = StringUtils.replace(bodyContent, url, newImgFileName); ImageUtils.copy(filePath + url, imgPath + uuid + extName); } } catch (ParserException e) { e.printStackTrace(); } String result = bodyContent; //去除多余的代码 result = StringUtils.replace(result, "<![endif]>", ""); result = StringUtils.replace(result, "<![if !vml]>", ""); bodyContent = null; return result; }
上面的代码中用到了开源的html解析工具htmlparser 用他来进行分析得到所有图片的链接 然后把图片的链接用Apache的Commons-lang包中的StrutsUtils替换成我修改了fck中预览图片的action
下面是我自己实现ImgTagVisitor 代码
- package com.bettem.cms.web.utils.htmlparser;
- import java.util.ArrayList;
- import java.util.List;
- import org.htmlparser.Tag;
- import org.htmlparser.Text;
- import org.htmlparser.visitors.NodeVisitor;
- /**
- *
- * 说明:htmlparser 解析 Img 标签所用类
- * *******************
- * 日期 人员
- * 2010-2-3 Liqiang
- */
- public class ImgTagVisitor extends NodeVisitor {
- private List<String> srcList;
- private StringBuffer textAccumulator;
- public ImgTagVisitor() {
- srcList = new ArrayList<String>();
- textAccumulator = new StringBuffer();
- }
- public void visitTag(Tag tag) {
- if (tag.getTagName().equalsIgnoreCase("img")) {
- srcList.add(tag.getAttribute("src"));
- }
- }
- public List<String> getSrcStringList() {
- return srcList;
- }
- public void visitStringNode(Text stringNode) {
- String text = stringNode.getText();
- textAccumulator.append(text);
- }
- public String getText() {
- return textAccumulator.toString();
- }
- }
package com.bettem.cms.web.utils.htmlparser; import java.util.ArrayList; import java.util.List; import org.htmlparser.Tag; import org.htmlparser.Text; import org.htmlparser.visitors.NodeVisitor; /** * * 说明:htmlparser 解析 Img 标签所用类 * ******************* * 日期 人员 * 2010-2-3 Liqiang */ public class ImgTagVisitor extends NodeVisitor { private List<String> srcList; private StringBuffer textAccumulator; public ImgTagVisitor() { srcList = new ArrayList<String>(); textAccumulator = new StringBuffer(); } public void visitTag(Tag tag) { if (tag.getTagName().equalsIgnoreCase("img")) { srcList.add(tag.getAttribute("src")); } } public List<String> getSrcStringList() { return srcList; } public void visitStringNode(Text stringNode) { String text = stringNode.getText(); textAccumulator.append(text); } public String getText() { return textAccumulator.toString(); } }
6.移除多余的v:imagedata标签
- /**
- * 移除多余的v:imagedata标签
- * @param content
- * @return
- */
- public static synchronized String removeImagedataTag(String content) {
- Parser parser = null;
- Lexer lexer = null;
- AndFilter andFilter = null;
- NodeList nl = null;
- try {
- parser = new Parser(content, Parser.STDOUT);
- lexer = new Lexer(content);
- andFilter = new AndFilter(new NotFilter(new TagNameFilter("v:imagedata")), new NotFilter(new TagNameFilter("v:imagedata")));
- nl = parser.extractAllNodesThatMatch(andFilter);
- } catch (ParserException e) {
- e.printStackTrace();
- }
- return nl.toHtml();
- }
/** * 移除多余的v:imagedata标签 * @param content * @return */ public static synchronized String removeImagedataTag(String content) { Parser parser = null; Lexer lexer = null; AndFilter andFilter = null; NodeList nl = null; try { parser = new Parser(content, Parser.STDOUT); lexer = new Lexer(content); andFilter = new AndFilter(new NotFilter(new TagNameFilter("v:imagedata")), new NotFilter(new TagNameFilter("v:imagedata"))); nl = parser.extractAllNodesThatMatch(andFilter); } catch (ParserException e) { e.printStackTrace(); } return nl.toHtml(); }
在word转html的时候大图片会被自动压缩成小图片 但是原来的大图片还会存在在代码里,上面的代码把多余的标签过滤掉.
最后看下我action中的代码
- /**
- * 导入word文件
- *
- * @return
- */
- public synchronized String exportWord()
- {
- String content = null;
- String path = ResourceBundle.getBundle("sysConfig").getString("userFilePath.word");
- InputStream ins = null;
- OutputStream wordFile = null;
- String htmlPath = null;
- String wordPath = null;
- // 处理上传的word文件
- try
- {
- String uuid = UUID.randomUUID().toString();
- // 截取扩展名
- String fileName = uuid + filedataFileName.substring(filedataFileName.lastIndexOf("."));
- // 生存html文件名
- String wordHtmlFileName = uuid + ".html";
- ins = new FileInputStream(filedata);
- wordPath = path + fileName;
- wordFile = new FileOutputStream(wordPath);
- IOUtils.copy(ins, wordFile);
- // word转html
- htmlPath = path + wordHtmlFileName;
- WordUtils.word2Html(wordPath, htmlPath);
- String wordHtmlContent = WordUtils.getHtmlCode(htmlPath);
- // 处理样式
- String styleCode = WordUtils.performStyleCode(wordHtmlContent);
- String bodyCode = WordUtils.performBodyCode(wordHtmlContent);
- // 处理文章中的图片
- bodyCode = WordUtils.performBodyImg(bodyCode);
- content = styleCode + bodyCode;
- styleCode = null;
- bodyCode = null;
- WordUtils.removeImagedataTag(content);
- }
- catch (FileNotFoundException e)
- {
- e.printStackTrace();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- finally
- {
- IOUtils.closeQuietly(wordFile);
- IOUtils.closeQuietly(ins);
- try
- {
- File word = new File(wordPath);
- File file = new File(htmlPath);
- if (file.exists())
- {
- file.delete();
- word.delete();
- FileUtils.deleteDirectory(new File(htmlPath.substring(0, htmlPath.lastIndexOf(".")) + ".files"));
- }
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- }
- // 读取word文件内容,添加到content中
- // 放到request中
- ServletActionContext.getRequest().setAttribute("content", content);
- ServletActionContext.getRequest().setAttribute("add", true);
- return SUCCESS;
- }
/** * 导入word文件 * * @return */ public synchronized String exportWord() { String content = null; String path = ResourceBundle.getBundle("sysConfig").getString("userFilePath.word"); InputStream ins = null; OutputStream wordFile = null; String htmlPath = null; String wordPath = null; // 处理上传的word文件 try { String uuid = UUID.randomUUID().toString(); // 截取扩展名 String fileName = uuid + filedataFileName.substring(filedataFileName.lastIndexOf(".")); // 生存html文件名 String wordHtmlFileName = uuid + ".html"; ins = new FileInputStream(filedata); wordPath = path + fileName; wordFile = new FileOutputStream(wordPath); IOUtils.copy(ins, wordFile); // word转html htmlPath = path + wordHtmlFileName; WordUtils.word2Html(wordPath, htmlPath); String wordHtmlContent = WordUtils.getHtmlCode(htmlPath); // 处理样式 String styleCode = WordUtils.performStyleCode(wordHtmlContent); String bodyCode = WordUtils.performBodyCode(wordHtmlContent); // 处理文章中的图片 bodyCode = WordUtils.performBodyImg(bodyCode); content = styleCode + bodyCode; styleCode = null; bodyCode = null; WordUtils.removeImagedataTag(content); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(wordFile); IOUtils.closeQuietly(ins); try { File word = new File(wordPath); File file = new File(htmlPath); if (file.exists()) { file.delete(); word.delete(); FileUtils.deleteDirectory(new File(htmlPath.substring(0, htmlPath.lastIndexOf(".")) + ".files")); } } catch (IOException e) { e.printStackTrace(); } } // 读取word文件内容,添加到content中 // 放到request中 ServletActionContext.getRequest().setAttribute("content", content); ServletActionContext.getRequest().setAttribute("add", true); return SUCCESS; }
评论
7 楼
zpl
2012-02-14
C:\Documents and Settings\Administrator\桌面
6 楼
zpl
2012-02-14
[img][/img] asdfasdfasdfa
5 楼
fonkyjon
2011-10-11
兄弟,有没有整个可以下载的Demo project出来啊?
4 楼
Jackie_GP
2011-07-03
这个功能比较鸡肋呀!不能跨平台,服务器必须安装Word才可以的呀!不如用POI实现的好呀!
3 楼
Jackie_GP
2011-07-01
可惜代码没有给全呀
2 楼
Mybeautiful
2010-12-15
兄弟,有没有整个可以下载的Demo project出来啊?
1 楼
yuan_xulong
2010-12-10
正好需要,谢谢兄弟了。
相关推荐
在这里我们要实现直接导入word文档,如果其中包含图片,则自动分离图片并上传到服务器后在fckeditor中显示. 参照下面链接文章 http://hi.baidu.com/wodally/blog/item/06527cfa450577284f4aeaac.html
Fckeditor java示例,下载后可以直接运行
FCKeditor & FCKeditor.java & fck-faces
添加了导入word功能,实现上传word文档至编辑器中。
FCKeditor+java 实现的网络相册 效果不比任何网站的次 部署到 eclipse 或者MyEclipse下 及可运行 带原码
java配置fckeditor完整包,在线编辑器,fckeditor,java
主要用AjaxPro将Fckeditor编辑器中的HTML代码发送到后台用Regex查找图片用WebClient下载图片,替换图片链接,回发信息,替换Fckeditor编辑器中的代码来实现将复制到编辑器中的图片下载到本地文件夹中。
fckeditor java网页在线日志编辑器 fckeditor java网页在线日志编辑器
fckeditor确实功能强大,但使用和配置也挺复杂。该资源是fckeditor在java web工程中的应用范例,使用方法可以参考我的博客fckEditor java使用,可结合Struts2 或参考其中的readme.txt
首先去下载FCKEditor2.6.3(当然本文编写的时候,这个是最新版本,也许你现在看到的已经是更新的版本了,... 第二是FCKeditor.Java(fckeditor-java-2.4.1-bin.zip),就是在Java代码中使用FCKEditor的相关工具类;
FCKEditor for java FCKEditor for java FCKEditor for java FCKEditor for java
fckeditor-java-2.4.1-bin和 fckeditor-java-2.4.1-src配套使用
fckeditor-java-2.6-src 源文件 示例 使用详解
FCKeditor_2.6.6.zip+fckeditor-java-2.4.1.rar+fckeditor-java-2.4.1-bin.zip+fckeditor-java-2.4-src.zip+fckeditor-java-demo-2.4.war.zip 分享几个包,让你学习有成。加油
由官网FCKeditor_2.6.4+fckeditor-java-2.4.1修改。 修改内容有: 1、上传的文件名为中文会变成乱码 2、新建中文目录变乱码(这个好似还有点小问题,不过不影响使用,还是不建议用中文目录) 3、对上传的文件使用...
fckeditor for JAVA所需要的所有文件 包括: FCKeditor_2.6.3.zip //主文件 fckeditor-java-2.4.1-bin.zip //jsp整合包 fckeditor-java-demo-2.4.1.war //完整的项目实例,建议部署到服务器上面看一下这个然后...
FCKeditor.java-2.3.2 + FCKeditor_2.5.1 + 中文API 黄金搭档! 最近做项目需要jsp里使用编辑器,在网上搜资料 几乎前篇一律, 版本太多,一晚上没睡 调试通了!有兴趣的可以研究下!
fckeditor java 2.6 2.3 jar, fckeditor,里面很全,是我找的所有jar包,基本可以满足需要
内附FCKEditor源代码,及其应用于Java Web程序相关包,并包含使用示例
这个是Fckeditor的java包,针对connectorServlet.java进行过修改其上传功能,