`
qq200874
  • 浏览: 11869 次
  • 性别: Icon_minigender_1
  • 来自: 太原
社区版块
存档分类
最新评论

导入word到Fckeditor(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; 
    } 

  }
 
上面的代码其实完成的功能其实就是通过调用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文件就是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;
	}
 
 
 转成的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;
	}
 
     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;
	}
 
 上面的代码中用到了开源的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(); 
  } 

}
 
   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();

	}
 
      在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; 
        }
 
    好了 就到这里吧 相信大家会有收获,我陆续还会贴出更多关于fckeditor的文章,请大家多多关注本blog
  
 
4
0
分享到:
评论
2 楼 千之夜 2013-11-26  
是啊。我还是没明白怎么调用这些方法。有没有事例
1 楼 fonkyjon 2011-10-11  
很好
博主能不能给个demo源码?

相关推荐

    java fckeditor所需jar包

    - **导入jar包**:你需要将这些jar文件添加到项目的类路径中,通常包括fckeditor.jar和可能的依赖库,以便在服务器端调用FCKeditor的相关API。 - **配置Servlet**:FCKeditor通过一个Servlet来处理上传和其它...

    fckeditor源文件和demo

    开发者可以直接将这些库导入到他们的Java项目中,快速实现富文本编辑功能,而无需从源码编译。通常,bin包会提供一个jar文件,可以作为依赖添加到构建路径中,使得FCKeditor的功能可以轻松地集成到其他Java应用程序...

    FCKeditor的jar包

    1. **导入jar包**:将`fckeditor-java-2.4.1.jar`添加到你的项目类路径中,这样你的Java应用就能访问到FCKeditor的API。 2. **配置编辑器**:在HTML页面中嵌入FCKeditor的JavaScript代码,指定服务器端处理文件上传...

    FCKEditor 2.6 for java jsp

    1. **下载与导入**:从官方或者其他可靠来源下载FCKEditor 2.6的Java JSP版本,解压后将相关文件导入到MyEclipse项目中。 2. **配置路径**:根据项目结构配置编辑器的路径,如图片上传目录、Flash存储位置等。 3. **...

    FCKeditor-2.2.gz

    FCKeditor是一款非常知名的开源富文本编辑器,广泛应用于网页制作和内容管理系统中,为用户提供了一个类似Microsoft Word的在线编辑体验。"FCKeditor-2.2.gz" 是该编辑器的一个版本,它以gzip压缩格式提供,可以节省...

    FCKeditor2.6.3完整包下载(全)

    FCKeditor是一款开源的网页文本编辑器,广泛应用于网站建设和内容管理系统中,为用户提供类似Microsoft Word的富文本编辑体验。2.6.3版本是其发展中的一个重要里程碑,提供了稳定性和功能性的提升。 FCKeditor2.6.3...

    FCKeditor-2.3案例直接导入MYECLIPSE

    FCKeditor是一款经典的开源富文本编辑器,广泛应用于网页开发中,允许用户在网页上进行类似于Word的文本编辑。FCKeditor 2.3是其一个版本,它提供了丰富的功能,如字体样式调整、图像上传、链接管理等,极大地提升了...

    fckeditor测试案例

    在Java项目中,首先需要将FCKeditor的源文件和相关的jar包导入到项目中。这些jar文件通常包含对Servlet的支持和其他必要的库。在MyEclipse中,你可以通过右键点击项目,选择“Build Path” &gt; “Configure Build Path...

    jsp调用FCKeditor 实例

    在Web开发中,常常需要提供用户友好的文本编辑功能,FCKeditor便是一个流行的开源富文本编辑器,它允许用户在网页上进行类似Word的文本编辑操作。本实例是关于如何在JavaServer Pages(JSP)中集成并调用FCKeditor,...

    FCKeditor实例下载

    FCKeditor实例下载提供了在Eclipse环境下集成和测试FCKeditor的机会,对于学习和理解如何在Java Web项目中实现富文本编辑功能非常有帮助。通过实践这个例子,你可以深入掌握FCKeditor的使用方法,并了解到如何与后端...

    Fckeditor完美结合Struts2.doc

    接下来,需要将`fckeditor-java-core`的jar包导入到项目中的`WEB-INF/lib`目录。这个库提供了与Java应用交互的接口,使得Struts2可以与Fckeditor通信。 **步骤3:处理依赖库** 在这个步骤中,需要注意避免重复引入...

    在线编辑java

    【标题】:“在线编辑java”指的是使用Java技术实现的在线文本编辑器,特别是这里提到的FCKeditor-2.3版本。FCKeditor是一个流行的开源富文本编辑器,它允许用户在网页上进行类似Word的文本编辑操作,包括格式化、...

    Fckeditor和数据库相关

    在IT领域,FCKeditor是一款著名的开源富文本编辑器,它允许用户在网页上进行类似Word的文本编辑,广泛应用于内容管理系统(CMS)、论坛和其他需要用户输入格式化文本的场景。这篇博客文章可能探讨了如何将FCKeditor...

    fckeditor在线编辑器myeclipse包括源代码

    FCKeditor是一款开源的富文本编辑器,它允许用户在网页上进行类似Word的文本编辑操作。FCKeditor的核心功能包括文本格式化、图像上传、链接创建、表格编辑等,为Web应用提供了强大的内容编辑解决方案。这款编辑器...

    fckeditor 在 jdeveloper 下的配置

    2. **导入FCKeditor到JDeveloper项目**: 在JDeveloper中,打开你的项目,然后通过“File”菜单选择“Import”,在弹出的对话框中,选择“Files and Folders”,将解压后的FCKeditor文件夹引入到你的Web应用项目的Web...

    fck框架,eclipse和myeclipse导入即用

    将FCK框架导入Eclipse或MyEclipse,首先需要下载FCKeditor的源码或库文件,然后通过“File”菜单的“Import”选项,选择相应的项目类型(如现有项目到工作区)进行导入。确保你的项目构建路径包含了FCKeditor所需的...

    fckeditor与jsp

    2. **导入FCKeditor**:将之前解压的FCKeditor文件夹放入WebContent目录下。 3. **编写JSP页面**:按照上述步骤创建包含FCKeditor的JSP页面。 4. **配置部署**:在MyEclipse中右键点击项目,选择"Run As" -&gt; "Run on...

    freemarker+fckeditor+struts+hibernate

    用户可能需要解压并导入到IDE,配置好数据库连接,然后运行来体验这个整合的系统。 总的来说,这个项目是一个典型的Java Web应用开发实例,通过整合这些流行的技术,实现了前后端分离,以及高效的数据管理和用户...

    FCKeditor编辑器

    “直接导入eclipse就能用”表明这个版本的FCKeditor是与Eclipse IDE兼容的,Eclipse是一款广泛使用的Java开发工具。开发者可以直接将FCKeditor的源码或者编译后的文件导入到Eclipse项目中,无需额外的配置步骤,简化...

    web所用的java插件包

    这个“web所用的java插件包”是一个专门为Java Web开发者设计的工具集合,包含了几个关键的插件组件,如JSvalidation、FCKeditor和dbutl。 首先,JSvalidation插件是专门用于前端表单验证的工具。在Web应用中,用户...

Global site tag (gtag.js) - Google Analytics