请上传宽度大于 1200px,高度大于 164px 的封面图片
    调整图片尺寸与位置
    滚轮可以放大缩小图片尺寸,按住图片拖动可调整位置,多余的会自动被裁剪掉
取消
roswell(uid:91439)
职业资格认证:尚未取得认证
报表中呈现金蝶K3存放于数据库中经压缩过的大文本(续)
原贴见 报表中呈现金蝶K3存放于数据库中经压缩过的大文本 上次解决K3中经kdzip.dll压缩存储到数据库中的富文本内容产生了几个问题,一是kdzip.dll调用要使用32 位JDK,造成报表系统性能低下,经常报超出内存错误。二是kdzip解压要先生成待解压文件,然后通过对这个文件解压后重新生成一个文件,效率较差。 经过向金蝶公司提单要求解决kdzip.dll64位文件问题,得到的答复是此文件是通过对zlib.lib静态库二次开发得来的,网上搜索了一大堆资料,发现JAVA原生的java.util.zip也是使用zlib压缩算法,接下来事情就变得简单多了,在原有代码上进行了修改。package com.fr.function; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.util.Arrays; import java.util.zip.DataFormatException; import java.util.zip.Inflater; import com.fr.data.core.db.*; import com.fr.script.AbstractFunction; import com.fr.stable.ArrayUtils; import com.fr.stable.Primitive; import javax.swing.JEditorPane; import javax.swing.text.BadLocationException; import javax.swing.text.EditorKit; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class getK3ZipRTF extends AbstractFunction{ private static final long serialVersionUID = 1L; @Override public Object run(Object args) { // TODO Auto-generated method stub if(ArrayUtils.getLength(args)!=1) { return Primitive.ERROR_VALUE; } return getK3Rtf2Html((BinaryObject)args); } /*** * * @param data 从数据库取得的IMAGE类型数据 * @return 解压后的字节数组 */ private static byte decompress(BinaryObject data) { byte bt=data.getBytes(); Inflater decompresser=new Inflater(); //压缩对象 decompresser.reset(); //清空对象数据 decompresser.setInput(bt);//入入待解压二进制数 int len=-1; byte buf=new byte; try { len=decompresser.inflate(buf); //解压后的数据写入字节数组,并获得数据长度 } catch (DataFormatException e) { e.printStackTrace(); } decompresser.end(); //结束解压 return Arrays.copyOf(buf,len); } private static String getK3Rtf2Html(BinaryObject ins) { String insNew=null; byte b=decompress(ins); //解压后的字节数组 InputStream is=new ByteArrayInputStream(b); //读入InputStream try { insNew= rtfToHtml(is); //将输入流转为HTML } catch (IOException e) { e.printStackTrace(); } try { insNew= new String(insNew.getBytes("Cp1252"), "GB2312"); //编码转换为GB2312 insNew=convertText(insNew); //提取元素标签并进行转换 } catch (UnsupportedEncodingException e) { e.printStackTrace(); } try { is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return insNew; } /*** * * @param in输入流 * @return 输出String格式的HTML * @throws IOException */ private static String rtfToHtml(InputStream in) throws IOException { JEditorPane p = new JEditorPane(); p.setContentType("text/rtf"); EditorKit kitRtf = p.getEditorKitForContentType("text/rtf"); try { kitRtf.read(in, p.getDocument(), 0); //inputstream转成文档 kitRtf = null; EditorKit kitHtml = p.getEditorKitForContentType("text/html"); Writer writer = new StringWriter(); kitHtml.write(writer, p.getDocument(), 0, p.getDocument().getLength()); return writer.toString(); } catch (BadLocationException e) { e.printStackTrace(); } return null; } /*** * * @param HTML格式的字串 * @return 处理过的字串 */ private static String convertText(String text) { if(text!=null) { Document doc=Jsoup.parse(text); Elements links=doc.getElementsByTag("span"); StringBuffer buffer=new StringBuffer(); for(Element link:links) { buffer.append(link.text().trim()+""); } return buffer.toString().trim(); } return null; } } 通过代码的优化,从原来要 生成文件--解压文件--生成新的解压文件-读取文件的方式直接通过字节数组来操作,优化了性能。 目前,已将报表系统换成了64位,一天运行下来,没有因内存溢出出现任何问题,稳定性有了极大提升,较完美的解决了这一个问题,同理对于其它保存在数据库中的压缩图片等文件也可以通过此方法来解决。 编辑于 2018-10-6 16:18 编辑于 2018-10-6 16:28
报表中呈现金蝶K3存放于数据库中经加密过的大文本内容
需求: 公司多年来使用K3 ERP,存在大量二次开发的内容,其中就有一部分是K3中开发的大文本控件内容存入数据库中的情形,现在想在FR中呈现这一内容。看起来需求很简单,但在解决过程中碰到很多坑,本着共享的精神,提供出来,给有类似需求的人一点提示。 思路:1、K3中存放于数据库中的大文本内容是经过KDZIP.DLL这个32位组件(强调这个32位是因为至今我也没能解决的坑)加密过的,必须要解密方能读取,首先就是解决Java调用dll组件问题。2、正确解密后会生成一个RTF格式的文本文件,如何正确解析RTF格式成HTML的问题。 3、如果仅需要HTML中的部分内容,如何根据标签提取HTML文本的问题。 解决方法: 1、JAVA调用32位DLL组件网上有很多方法供使用,我采用的是JaCob组件,网上下载jocab 1.18的版本,取得2个文件,这里调用的是32位DLL,因此要使用32位的jacob-1.18-x86.dll,而且必须要使用32位的JDK,这几个必须保持一致,否则调用会失败。1139002、将jacob.jar包放到项目的lib目录下,jacob-1.18-x86.dll放到JDK的BIN目录下,拷贝K3中的KDZIP.dll到System32目录下,并通过regsvr32注册。第一步的准备工作就完成了。2、涉及到HTML处理的问题,无非是使用JEditorPane控件处理。3、抽取HTML操作,使用了jsoup-1.11.3.jar包 getK3ZipRTF.javapackage com.fr.function; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; import com.fr.data.core.db.*; import com.fr.script.AbstractFunction; import com.fr.stable.ArrayUtils; import com.fr.stable.Primitive; import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComThread; import com.jacob.com.Dispatch; import javax.swing.JEditorPane; import javax.swing.text.BadLocationException; import javax.swing.text.EditorKit; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class getK3ZipRTF extends AbstractFunction { @Override public Object run(Object args) { // TODO Auto-generated method stub if(ArrayUtils.getLength(args)!=1) { return Primitive.ERROR_VALUE; } return getK3Rtf2Html((BinaryObject)args); } private static boolean readDb(BinaryObject ins) { byte bt=ins.getBytes();// return byte2File(bt,"c:\\","tmp.tmp"); //二进制内容临时保存成一个文件 } /** * 调用KDZIP组件中的DeCompress方法进行解密 * @param sFile 源文件 * @param tFile 解密后的文件 * @return 成功返回TRUE */ private static boolean DeCompress(String sFile,String tFile) { boolean returnV=false; ComThread.InitSTA(); try { ActiveXComponent com =new ActiveXComponent("KDZIP.ZIP"); //ActiveXComponent com =new ActiveXComponent("Word.Application"); Dispatch disp=(Dispatch) com.getObject(); Dispatch.call(disp,"DeCompress",sFile,tFile); returnV=true; } catch(Exception e) { e.printStackTrace(); } ComThread.Release(); return returnV; } /** * 将解密后的RTF转换成HTML格式 * @param ins * @return */ private static String getK3Rtf2Html(BinaryObject ins) { String insNew=null; //byte nbt=null; boolean isok= readDb(ins); // 获得数据库中的IMAGE类型转成文 件 if(isok) { if(DeCompress("c:\\tmp.tmp","c:\\newTemp.RTF")) { //将目标文件转成相应文件文件流 //nbt=file2Byte("c:\\newTemp"+"."+fileType); try { insNew= rtfToHtml(new FileReader(new File("c:\\newTemp.RTF"))); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //System.out.println(insNew); try { insNew= new String(insNew.getBytes("Cp1252"), "GB2312");//重要:错误的编码格式转换会造成读取乱码 insNew=convertText(insNew); //提取HTML中的指定标签中的内容 } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return insNew; } /** * 将字节流转存为文件 * @param bfile * @param fPath * @param fName * @return */ private static boolean byte2File(byte bfile,String fPath,String fName){ boolean b=false; BufferedOutputStream bos=null; FileOutputStream fos=null; File file=null; try { File dir=new File(fPath); if(!dir.exists()&&!dir.isDirectory()) { dir.mkdirs(); } file=new File(fPath+fName); fos=new FileOutputStream(file); bos=new BufferedOutputStream(fos); bos.write(bfile); b=true; } catch(Exception e) { e.printStackTrace(); } finally { try { if(bos!=null) { bos.close(); } if(fos!=null) { fos.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return b; } /** * * @param rtf RTF格式文件 * @return 返回转换成字符串格式的HTML文本 * @throws IOException */ private static String rtfToHtml(Reader rtf) throws IOException { JEditorPane p = new JEditorPane(); p.setContentType("text/rtf"); EditorKit kitRtf = p.getEditorKitForContentType("text/rtf"); try { kitRtf.read(rtf, p.getDocument(), 0); kitRtf = null; EditorKit kitHtml = p.getEditorKitForContentType("text/html"); Writer writer = new StringWriter(); kitHtml.write(writer, p.getDocument(), 0, p.getDocument().getLength()); return writer.toString(); } catch (BadLocationException e) { e.printStackTrace(); } return null; } /** * * @param Text HTML格式文件 * @return 抽取出的格式文本 */ private static String convertText(String text) { if(text!=null) { Document doc=Jsoup.parse(text); // Elements links=doc.getElementsByTag("span"); //根据标签取得内容 StringBuffer buffer=new StringBuffer(); //写入缓冲 for(Element link:links) { buffer.append(link.text().trim()+"");//对文本进行分段 } return buffer.toString().trim(); } return null; } }将生成的class放入项目下的classes\com\fr\function文件夹中,在通过设计器的函数管理器中添加相应的函数。113902涂颜色的地方都是直接读取数据库中加密IMAGE文件后,使用getK3ZipRTF($$$)进行数据转换,然后使用HTML方式查看内容。实际显示效果:113904 不足:报表已正常运行了几周,但因为使用32位JDK,内存上面的先天限制,造成报表性能较低,后续正在查找64位的DLL来代替,或者可以用什么方法可以使用64位去封装32位的DLL,现在还没有头绪,也顺请大神能提供方法,感谢! 编辑于 2018-8-15 14:16
个人成就
内容被浏览15,188
加入社区7年113天
返回顶部