报表中呈现金蝶K3存放于数据库中经加密过的大文本内容

我是社区第91439位番薯,欢迎点我头像关注我哦~
需求:
    公司多年来使用K3 ERP,存在大量二次开发的内容,其中就有一部分是K3中开发的大文本控件内容存入数据库中的情形,现在想在FR中呈现这一内容。看起来需求很简单,但在解决过程中碰到很多坑,本着共享的精神,提供出来,给有类似需求的人一点提示。

思路:
1K3中存放于数据库中的大文本内容是经过KDZIP.DLL这个32位组件(强调这个32位是因为至今我也没能解决的坑)加密过的,必须要解密方能读取,首先就是解决Java调用dll组件问题。
2、正确解密后会生成一个RTF格式的文本文件,如何正确解析RTF格式成HTML的问题。

3、如果仅需要HTML中的部分内容,如何根据标签提取HTML文本的问题。

解决方法:

1JAVA调用32DLL组件网上有很多方法供使用,我采用的是JaCob组件,网上下载jocab 1.18的版本,取得2个文件,这里调用的是32DLL,因此要使用32位的jacob-1.18-x86.dll,而且必须要使用32位的JDK,这几个必须保持一致,否则调用会失败。
截图201808151337478540.png
2、jacob.jar包放到项目的lib目录下,jacob-1.18-x86.dll放到JDKBIN目录下,拷贝K3中的KDZIP.dllSystem32目录下,并通过regsvr32注册。第一步的准备工作就完成了。
2、涉及到HTML处理的问题,无非是使用JEditorPane控件处理。
3、抽取HTML操作,使用了jsoup-1.11.3.jar

getK3ZipRTF.java
  1. package com.fr.function;

  2. import java.io.BufferedOutputStream;
  3. import java.io.File;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.FileReader;
  7. import java.io.IOException;
  8. import java.io.Reader;
  9. import java.io.StringWriter;
  10. import java.io.UnsupportedEncodingException;
  11. import java.io.Writer;
  12. import com.fr.data.core.db.*;
  13. import com.fr.script.AbstractFunction;
  14. import com.fr.stable.ArrayUtils;
  15. import com.fr.stable.Primitive;
  16. import com.jacob.activeX.ActiveXComponent;
  17. import com.jacob.com.ComThread;
  18. import com.jacob.com.Dispatch;
  19. import javax.swing.JEditorPane;
  20. import javax.swing.text.BadLocationException;
  21. import javax.swing.text.EditorKit;
  22. import org.jsoup.Jsoup;
  23. import org.jsoup.nodes.Document;
  24. import org.jsoup.nodes.Element;
  25. import org.jsoup.select.Elements;


  26. public class getK3ZipRTF extends AbstractFunction {
  27.    @Override
  28.    public Object run(Object[] args) {
  29.    // TODO Auto-generated method stub
  30.         if(ArrayUtils.getLength(args)!=1) {
  31.             return Primitive.ERROR_VALUE;
  32.         }
  33.    return getK3Rtf2Html((BinaryObject)args[0]);
  34.         }
  35.         private static boolean readDb(BinaryObject ins) {
  36.                 byte[] bt=ins.getBytes();//
  37.                 return byte2File(bt,"c:\\","tmp.tmp");        //二进制内容临时保存成一个文件               
  38.         }
  39.         /**
  40.          * 调用KDZIP组件中的DeCompress方法进行解密
  41.          * @param sFile 源文件
  42.          * @param tFile 解密后的文件
  43.          * @return 成功返回TRUE
  44.          */
  45.         private static boolean DeCompress(String sFile,String tFile)
  46.         {                 
  47.                 boolean returnV=false;
  48.                 ComThread.InitSTA();                        
  49.                 try {
  50.                         ActiveXComponent com =new ActiveXComponent("KDZIP.ZIP");
  51.                         //ActiveXComponent com =new ActiveXComponent("Word.Application");
  52.                         Dispatch disp=(Dispatch) com.getObject();
  53.                         Dispatch.call(disp,"DeCompress",sFile,tFile);
  54.                         returnV=true;
  55.                 }
  56.                 catch(Exception e) {
  57.                         e.printStackTrace();
  58.                 }
  59.                 ComThread.Release();
  60.                 return returnV;
  61.         }
  62.         /**
  63.          * 将解密后的RTF转换成HTML格式
  64.          * @param ins
  65.          * @return
  66.          */
  67.         private static String getK3Rtf2Html(BinaryObject ins)
  68.         {
  69.                 String insNew=null;
  70.                 //byte[] nbt=null;
  71.                 boolean isok= readDb(ins); // 获得数据库中的IMAGE类型转成文 件
  72.                 if(isok) {
  73.                         if(DeCompress("c:\\tmp.tmp","c:\\newTemp.RTF")) {
  74.                                 //将目标文件转成相应文件文件流
  75.                                 //nbt=file2Byte("c:\\newTemp"+"."+fileType);
  76.                                 try {
  77.                                         insNew= rtfToHtml(new FileReader(new File("c:\\newTemp.RTF")));
  78.                                 } catch (FileNotFoundException e) {
  79.                                         // TODO Auto-generated catch block
  80.                                         e.printStackTrace();
  81.                                 } catch (IOException e) {
  82.                                         // TODO Auto-generated catch block
  83.                                         e.printStackTrace();
  84.                                 }
  85.                         }
  86.                 }        
  87.                 //System.out.println(insNew);
  88.                 try {
  89.                         insNew= new String(insNew.getBytes("Cp1252"), "GB2312");//重要:错误的编码格式转换会造成读取乱码
  90.                         insNew=convertText(insNew);        //提取HTML中的指定标签中的内容               
  91.                 } catch (UnsupportedEncodingException e) {
  92.                         // TODO Auto-generated catch block
  93.                         e.printStackTrace();
  94.                 }
  95.                 return insNew;               
  96.         }
  97.         /**
  98.          * 将字节流转存为文件
  99.          * @param bfile
  100.          * @param fPath
  101.          * @param fName
  102.          * @return
  103.          */
  104.         private static boolean byte2File(byte[] bfile,String fPath,String fName){
  105.                 boolean b=false;
  106.                 BufferedOutputStream bos=null;
  107.                 FileOutputStream fos=null;
  108.                 File file=null;
  109.                 try {
  110.                         File dir=new File(fPath);
  111.                         if(!dir.exists()&&!dir.isDirectory()) {
  112.                                 dir.mkdirs();
  113.                         }
  114.                         file=new File(fPath+fName);
  115.                         fos=new FileOutputStream(file);
  116.                         bos=new BufferedOutputStream(fos);
  117.                         bos.write(bfile);
  118.                         b=true;                        
  119.                 }
  120.                 catch(Exception e) {
  121.                         e.printStackTrace();
  122.                 }
  123.                 finally {                        
  124.                                 try {
  125.                                         if(bos!=null) {
  126.                                                 bos.close();
  127.                                         }
  128.                                         if(fos!=null) {
  129.                                                 fos.close();
  130.                                         }
  131.                                 } catch (IOException e) {
  132.                                         // TODO Auto-generated catch block
  133.                                         e.printStackTrace();
  134.                                 }
  135.                 }
  136.                 return b;
  137.         }
  138.       
  139.         /**
  140.          *
  141.          * @param rtf RTF格式文件
  142.          * @return 返回转换成字符串格式的HTML文本
  143.          * @throws IOException
  144.          */
  145.         private static String rtfToHtml(Reader rtf) throws IOException {
  146.             JEditorPane p = new JEditorPane();
  147.             p.setContentType("text/rtf");
  148.            
  149.             EditorKit kitRtf = p.getEditorKitForContentType("text/rtf");
  150.             try {
  151.                 kitRtf.read(rtf, p.getDocument(), 0);
  152.                 kitRtf = null;               
  153.                 EditorKit kitHtml = p.getEditorKitForContentType("text/html");               
  154.                 Writer writer = new StringWriter();
  155.                 kitHtml.write(writer, p.getDocument(), 0, p.getDocument().getLength());
  156.                 return writer.toString();
  157.             } catch (BadLocationException e) {
  158.                 e.printStackTrace();
  159.             }
  160.             return null;
  161.         }
  162.         /**
  163.          *
  164.          * @param Text HTML格式文件
  165.          * @return 抽取出的格式文本
  166.          */
  167.         private static String convertText(String text) {
  168.                 if(text!=null) {
  169.                         Document doc=Jsoup.parse(text); //
  170.                         Elements links=doc.getElementsByTag("span"); //根据标签取得内容
  171.                         StringBuffer buffer=new StringBuffer(); //写入缓冲
  172.                                 for(Element link:links) {
  173.                                         buffer.append(link.text().trim()+"<br />");//对文本进行分段
  174.                                 }
  175.                                 return buffer.toString().trim();
  176.                 }
  177.                 return null;
  178.         }
  179. }
复制代码
将生成的class放入项目下的classes\com\fr\function文件夹中,在通过设计器的函数管理器中添加相应的函数。
截图201808151353336605.png
涂颜色的地方都是直接读取数据库中加密IMAGE文件后,使用getK3ZipRTF($$$)进行数据转换,然后使用HTML方式查看内容。
实际显示效果:
截图201808151358474692.png

不足:报表已正常运行了几周,但因为使用32位JDK,内存上面的先天限制,造成报表性能较低,后续正在查找64位的DLL来代替,或者可以用什么方法可以使用64位去封装32位的DLL,现在还没有头绪,也顺请大神能提供方法,感谢!


编辑于 2018-8-15 14:16  

发表于 2018-10-8 10:45:21
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1回帖数 1关注人数 5912浏览人数
最后回复于:2018-10-8 10:45

返回顶部 返回列表