在JadePool中,提供了一个 万能表单解析类ProcessForm,目的是提供对ProcessVO实现插入或更新记录的支持。 它能将任意复杂的表单记录,包括所有的字段,包括单记录和多记录,解析并封装成List<Map>变量,这些结果可以作为ProcessVO插入、更新等方法的参数保存到数据库中。保存记录时,ProcessVO会自动过滤掉无效字段,只有表单中的字段名与数据库表中的字段名相同的数据才会保存到数据库中。目前,ProcessForm可能是世界上最完整的表单解析工具。

ProcessForm支持所有格式的文件上传,但不支持大文件的上传,能满足大多数网络环境的应用。

对于文件类型的字段,除了会解析出文件的内容外,还会给出文件的相关属性,这些属性按照下面的格式命名:

文件字段名_originfilename
                文件字段名_filename
                文件字段名_ext
                文件字段名_contenttype
                文件字段名_size

对于四种常见的图片文件(jpg|gif|png|bmp),还会计算出图片宽度、高度等信息,
                文件字段名_width
                文件字段名_height

ProcessForm支持同步(非Ajax)和异步(Ajax)两种方式提交的表单的解析

为了保证得到正确的解析结果,在表单设计上,使用这两个属性值: method="post"enctype="multipart/form-data"

如果表单代表的是一条记录,对表单的字段顺序没有要求;如果表单代表的是多条记录,请不要把check、radio类型的字段作为每条记录的第一个字段,如果页面确实需要check、radio类型作为第一个字段,那么在check或radio之前加一个无效的隐含字段。ProcessVO不会保存无效字段值。

对于异步方式提交的表单数据,必须是Ajax标准格式,即xml格式。

ProcessForm应用:
        同步上传的表单解析

ProcessForm form = ProcessForm.instance();
        //form.setFilter("jpg|gif|png|swf");
        //form.setAllowFileSize(1024000);//单个文件允许达到1M
        form.parse(request);//同步解析

Map m = form.getRecordFullInfo();//包含文件的属性
        m = form.getRecord()
        List v = form.getRecordList();
        v = form.getRecordFullInfoList();//包含文件的附件属性

异步上传的表单解析

ProcessForm pf = ProcessForm.instance();
        pf.parseXML(request, pf.IS_ECMA_UNICODE);//表单字段的值均经过escape方法的处理
        pf.parseXML(request);
        List v = pf.getRecordList();

一点说明:由于表单解析程序的代码相当复杂,如果遇到不能解析的情况,请及时告诉本人。邮箱hkm2300(at)yahoo.com.cn

对同步方式提交的记录进行解析的部分底层核心方法

    /*** 对非ajax方式提交的记录解析。 解析 contentType = "multipart/form-data";的表单* 在表单中出现多条记录时,第一个元素作为新的一条记录的参考标志,必须确保其有一个固定的名称,所以表单中第一个元素应辟免使用checkbox复选框和radio单选按钮,以防止表的结构信息错误*/private List getMultipartFormData(HttpServletRequest request) throws IOException, ServletException {Map recordFullInfo = null;List _recordFullInfoList = new ArrayList();int recordIndex = -1;itemNameSet = new HashSet();ServletInputStream in = request.getInputStream();charset = request.getCharacterEncoding();int allowFileSize = this.getAllowFileSize();byte[] buffer = new byte[allowFileSize];int bufferLength = 0;byte[] temp;byte[] lineByte = new byte[4096];String line;String boundary = getBoundary(request);String itemName = "";String originFileName = "";String fileName = "";String fileExt = "";StringBuffer sb = new StringBuffer("");boolean nameFlag = false;boolean fileFlag = false;int skipLine = 0;int i;try {while ((line = this.readLine(lineByte, in, charset)) != null) {if (!nameFlag && !fileFlag) {itemName = getName(line);if (itemName != null && !"".equals(itemName.trim())) {itemNameSet.add(itemName);//保存表单中的域名if (recordIndex == -1) {firstItem = itemName;}if (firstItem.equals(itemName)) {recordIndex++;recordFullInfo = new HashMap();//_recordFullInfoList.add(recordIndex, recordFullInfo);}nameFlag = true;originFileName = this.getOriginFileName(line);fileName = getFileName(line);if (fileName != null && !"".equals(fileName)) {fileExt = getFileNameExt(fileName).toLowerCase();if ("".equals(filter)) {((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_originfilename", originFileName);((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_filename", fileName);((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_ext", fileExt);} else {if (this.matchesFile(fileExt, filter)) {((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_originfilename", originFileName);((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_filename", fileName);((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_ext", fileExt);} else {throw new ServletException("Not matches file!");}}fileFlag = true;} else {fileFlag = false;}skipLine = 0;continue;}continue;}if (nameFlag && !fileFlag) {if (skipLine < 1) {skipLine++;continue;} else {if (line.indexOf(boundary) >= 0) {nameFlag = false;//((Map) (_recordFullInfoList.get(recordIndex))).put(itemName, trim(sb.toString()));//保存普通字段名称和值String s = sb.toString();if (s.endsWith("\r\n")) {s = s.substring(0, s.length() - "\r\n".length());//去掉尾部的"\r\n"}if (s.endsWith("\r")) {s = s.substring(0, s.length() - "\r".length());//去掉尾部的"\r"}if (s.endsWith("\n")) {s = s.substring(0, s.length() - "\n".length());//去掉尾部的"\n"}((Map) (_recordFullInfoList.get(recordIndex))).put(itemName, s);//在最新测试中,不需要转换\r\n,保存普通字段名称和值sb = new StringBuffer("");} else {sb.append(line);}}continue;}if (nameFlag && fileFlag) {if (skipLine < 1) {if (line.indexOf("Content-Type:") >= 0) {String s = line.substring(14);//"Content-Type: "的长度。if (s.endsWith("\r\n")) {s = s.substring(0, s.length() - "\r\n".length());//去掉尾部的"\r\n"}if (s.endsWith("\r")) {s = s.substring(0, s.length() - "\r".length());//去掉尾部的"\r"}if (s.endsWith("\n")) {s = s.substring(0, s.length() - "\n".length());//去掉尾部的"\n"}//((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_contenttype", trim(line.substring(14)));//"Content-Type: "的长度((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_contenttype", s);} else {skipLine++;}continue;} else {//把文件保存到byte[]中if (line.indexOf(boundary) >= 0) {if (bufferLength >= 2) {bufferLength -= 2;if (bufferLength < Integer.MAX_VALUE) {if (bufferLength < this.getAllowFileSize()) {temp = new byte[bufferLength];for (i = 0; i < bufferLength; i++) {temp[i] = buffer[i];}((Map) (_recordFullInfoList.get(recordIndex))).put(itemName, temp);//将字段名和文件的字节数组保存到record中((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_size", temp.length);//将文件的长度大小保存到record中if (matchesFile(fileExt, "jpg|gif|png|bmp")) {//如果是图像文件,提取宽度和高度信息,并保存((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_width", this.getIgmWidth(temp));//将字段名和文件的字节数组保存到record中((Map) (_recordFullInfoList.get(recordIndex))).put(itemName + "_height", this.getIgmHeight(temp));//将字段名和文件的字节数组保存到record中}buffer = new byte[allowFileSize];bufferLength = 0;} else {throw new ArrayIndexOutOfBoundsException("java.lang.ArrayIndexOutOfBoundsException: the file is bigger than allowFileSize[" + getAllowFileSize() + "] ");}} else {throw new ArrayIndexOutOfBoundsException("java.lang.ArrayIndexOutOfBoundsException: the file is too big. the max allow is " + Integer.MAX_VALUE);}}nameFlag = false;fileFlag = false;} else {for (i = 0; i < LINE_LENGTH; i++, bufferLength++) {buffer[bufferLength] = lineByte[i];//将字节数据写入}}}}}} finally {in.close();}return _recordFullInfoList;}

对异步上传提交的记录进行解析的部分底层核心方法

    /*** 解析用xml格式保存的记录,如使用Ajax上传的xml代码 在xml代码中出现多条记录时,第一个元素作为新的一条记录的参考标志*/private List getListFromXml(String xmlFragment) throws ServletException {indexXmlList = -1;xmlRecordList = new ArrayList();itemNameSet = new HashSet();Document doc = null;try {DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();doc = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xmlFragment)));} catch (Exception e) {e.printStackTrace();}List list = visitNode(doc);return list;}/*** 解析用xml格式保存的记录,如使用Ajax上传的xml代码* 该记录的值经由escape(form.XXX.value)方法转换成JavaScript中的Unicode编码格式* 在xml代码中出现多条记录时,第一个元素作为新的一条记录的参考标志*/private List getListFromXml(String xmlFragment, boolean isEcmaUnicode) throws ServletException, UnsupportedEncodingException {indexXmlList = -1;xmlRecordList = new ArrayList();itemNameSet = new HashSet();Document doc = null;try {DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();doc = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xmlFragment)));} catch (Exception e) {e.printStackTrace();}List list = visitNode(doc, isEcmaUnicode);return list;}private List visitNode(Node node) throws ServletException {if (node.getNodeType() == 1) {Node text = node.getFirstChild();if (text != null) {if ("#text".equals(text.getNodeName())) {if (indexXmlList == -1) {firstXmlTagName = node.getNodeName();itemNameSet.add(firstXmlTagName);indexXmlList++;}if (firstXmlTagName.equals(node.getNodeName())) {xmlRecord = new HashMap();firstXmlTagParentNode = node.getParentNode();xmlRecordList.add(xmlRecord);indexXmlList++;}//如果当前的Element与第一个Element(字段)的父结点相同,则可以断定当前的Element肯定是字段if ((indexXmlList > -1) && firstXmlTagParentNode.equals(node.getParentNode())) {itemNameSet.add(node.getNodeName());((Map) xmlRecordList.get(indexXmlList - 1)).put(node.getNodeName(), text.getNodeValue());}}} else {//叶子结点肯定是字段,但这是一个空值字段if (indexXmlList == -1) {//throw new ServletException("The first element '<" + node.getNodeName() + ">' could not be null!");//禁止第一个字段为空值}if (indexXmlList == -1) {//允许第一个字段为空值firstXmlTagName = node.getNodeName();itemNameSet.add(firstXmlTagName);indexXmlList++;}if (firstXmlTagName.equals(node.getNodeName())) {xmlRecord = new HashMap();firstXmlTagParentNode = node.getParentNode();xmlRecordList.add(xmlRecord);indexXmlList++;}//如果当前的Element与第一个Element(字段)的父结点相同,则可以断定当前的Element的值为nullif ((indexXmlList > -1) && firstXmlTagParentNode.equals(node.getParentNode())) {itemNameSet.add(node.getNodeName());((Map) xmlRecordList.get(indexXmlList - 1)).put(node.getNodeName(), "");//用""替代null,还原表单的本义,如果元素存在,request.getParameter('元素名')则肯定会得到字符串,其长度大于等于0;如果元素不存在,request.getParameter('元素名')则肯定得到null}}}NodeList nodeList = node.getChildNodes();if (nodeList != null && nodeList.getLength() > 0) {for (int i = 0; i < nodeList.getLength(); i++) {Node childNode = nodeList.item(i);visitNode(childNode);}}return xmlRecordList;}/*** 解析ajax方式上传的xml格式的记录集。 为xml应用修改* 在ajax应用中如json,pvo中的Map对象,Array中元素,它们的值均不能含有回车符和换行符,因此 \r 将转换成"" \n 将转换成""* 此方法可以作为默认的xml解析方法,不论用户上传的数据是否作了escape转换,都能得到希望的结果*/private List visitNode(Node node, boolean isEcmaUnicode) throws ServletException, UnsupportedEncodingException {if (node.getNodeType() == 1) {//System.out.println("isEcmaUnicode 2 is  : " + isEcmaUnicode);Node text = node.getFirstChild();String value = "";if (text != null) {StringBuilder sb = new StringBuilder();if ("#text".equals(text.getNodeName())) {if (indexXmlList == -1) {firstXmlTagName = node.getNodeName();itemNameSet.add(firstXmlTagName);indexXmlList++;}if (firstXmlTagName.equals(node.getNodeName())) {xmlRecord = new HashMap();firstXmlTagParentNode = node.getParentNode();xmlRecordList.add(xmlRecord);indexXmlList++;}//如果当前的Element与第一个Element(字段)的父结点相同,则可以断定当前的Element的值为nullif ((indexXmlList > -1) && firstXmlTagParentNode.equals(node.getParentNode())) {itemNameSet.add(node.getNodeName());value = text.getNodeValue();String oneChar = "";//用于从value中逐个提取字符if (isEcmaUnicode && (value != null)) {while (value.length() > 0) {if (!value.startsWith("%")) {oneChar = value.substring(0, 1);if ("\n".equals(oneChar)) {//oneChar = "";oneChar = "#pvo_n#";//替换}if ("\r".equals(oneChar)) {//oneChar = "";oneChar = "#pvo_r#";//替换}sb.append(oneChar);value = value.substring(1);} else if (value.startsWith("%")) {if (value.startsWith("%u")) {oneChar = value.substring(2, 6);oneChar = ByteProcess.UnicodeHexCharsToString(oneChar);if ("\n".equals(oneChar)) {//oneChar = "";oneChar = "#pvo_n#";//替换}if ("\r".equals(oneChar)) {//oneChar = "";oneChar = "#pvo_r#";//替换}sb.append(oneChar);value = value.substring(6);} else {oneChar = "00" + value.substring(1, 3);oneChar = ByteProcess.UnicodeHexCharsToString(oneChar);if ("\n".equals(oneChar)) {//oneChar = "";oneChar = "#pvo_n#";//替换}if ("\r".equals(oneChar)) {//oneChar = "";oneChar = "#pvo_r#";//替换}sb.append(oneChar);value = value.substring(3);}}}}String s = sb.toString();if (s.endsWith("#pvo_r##pvo_n#")) {s = s.substring(0, s.length() - "#pvo_r##pvo_n#".length());//去掉尾部的"#pvo_r##pvo_n#"}if (s.endsWith("#pvo_r#")) {s = s.substring(0, s.length() - "#pvo_r#".length());//去掉尾部的"#pvo_r#"}if (s.endsWith("#pvo_n#")) {s = s.substring(0, s.length() - "#pvo_n#".length());//去掉尾部的"#pvo_n#"}s = this.replace(s, "#pvo_r##pvo_n#", "\r\n");//还原s = this.replace(s, "#pvo_n#", "\n");//还原s = this.replace(s, "#pvo_r#", "\r");//还原((Map) xmlRecordList.get(indexXmlList - 1)).put(node.getNodeName(), s);}}} else {//叶子结点肯定是字段,但这是一个空值字段if (indexXmlList == -1) {//throw new ServletException("The first element '<" + node.getNodeName() + ">' could not be null!");//禁止第一个字段为空值}if (indexXmlList == -1) {//允许第一个字段为空值firstXmlTagName = node.getNodeName();itemNameSet.add(firstXmlTagName);indexXmlList++;}if (firstXmlTagName.equals(node.getNodeName())) {xmlRecord = new HashMap();firstXmlTagParentNode = node.getParentNode();xmlRecordList.add(xmlRecord);indexXmlList++;}//如果当前的Element与第一个Element(字段)的父结点相同,则可以断定当前的Element的值为nullif ((indexXmlList > -1) && firstXmlTagParentNode.equals(node.getParentNode())) {itemNameSet.add(node.getNodeName());((Map) xmlRecordList.get(indexXmlList - 1)).put(node.getNodeName(), "");//用""替代null,还原表单的本义,如果元素存在,request.getParameter('元素名')则肯定会得到字符串,其长度大于等于0;如果元素不存在,request.getParameter('元素名')则肯定得到null}}}NodeList nodeList = node.getChildNodes();if (nodeList != null && nodeList.getLength() > 0) {for (int i = 0; i < nodeList.getLength(); i++) {Node childNode = nodeList.item(i);visitNode(childNode, isEcmaUnicode);}}return xmlRecordList;}

使用万能表单解析程序将表单数据封装成ListMap相关推荐

  1. php单页程序,动态php单页站群源码,泛解析单页循环暴力域名站群系统

    本程序是一个不需要数据库的动态php单页站群源码,动态版,需要php+zend环境支持,需要域名泛解析,需要独立主机或者vps支持,虚拟主机暂时无法达到效果, 设置好以后只需在文本导入你的关键词和文章 ...

  2. 万能表单解析工具在xheditor上传文件中的应用

    利用JadePool中的万能表单解析工具cn.jadepool.web.ProcessForm可以轻松解析表单提交的全部信息,甚至可以轻松获取一个未知结构的表单由那些字段组成.以下是在xheditor ...

  3. c# timer 销毁_如果表单应用程序关闭C#,如何防止发生Timer Elapsed事件

    我在 Windows窗体应用程序(Visual C#)中有一个计时器,当我想退出应用程序时,它会导致问题. 计时器被定义为表单类的成员: partial class Form1 { //These a ...

  4. 微信小程序插件---表单验证篇

    微信小程序插件---表单验证篇 项目下载地址 WxValidate - 表单验证 插件介绍 该插件是参考 jQuery Validate 封装的,为小程序表单提供了一套常用的验证规则,包括手机号码.电 ...

  5. 微信小程序提交表单数据Cannot read property ‘***‘ of undefined?

    前一阵子写小程序的时候写了一个提交表单数据到数据库的页面,代码如下 结果我一提交 这特喵的什么玩意?然后我console了一下收集到的数据 ??????这都是些什么玩意儿 我寻思着按这个submit按 ...

  6. 微信小程序常用表单组件

    微信小程序常用表单组件 1.常用表单组件 1.1 button 1.2 checkbox 1.3 input 1.4 label 1.5 form 1.6 radio 1.7 slider 1.8 s ...

  7. 【微信小程序】表单提交验证及获取表单输入的值

    效果图: 说明:请选择房屋所在城市的效果是省市区选择器,刚开始我们可能直接在picker选择器中直接包含一个input输入框实现,但是这样的话点击选择的话可能聚焦在输入框中,我们想要的效果是点击的时候 ...

  8. 微信小程序 form表单验证

    业务需求:微信小程序提交表单的时候必填的项要提示,还要电话要校验 首页,先搞一个校验的公共方法 validate.js /*** 表单验证* * @param {Object} rules 验证字段的 ...

  9. MySQL将表中的yes改成no_mysql在不需要改程序的情况下通过操作数据库对单表数据量大的表进行分表...

    1.为什么要分表? 数据库数据越来越大,随之而来的是单个表中数据太多.以至于查询速度变慢,而且由于表的锁机制导致应用操作也搜到严重影响,出现了数据库性能瓶颈. mysql中有一种机制是表锁定和行锁定, ...

最新文章

  1. 文件操作示例脚本 tcl
  2. WordPress开发之WP Custom Register Login插件试用
  3. linux-查看用户id-查看文件目录所有者-查看进程操作者
  4. Android 系统(90)---JIT 编译器
  5. 根据div 标签 查看数组@class=modulwrap 下面的/table/tbody/tr/td
  6. [教程]控制反转(IoC)与依赖注入(DI)
  7. m1 mac屏幕保护程序取消不了怎么办
  8. 楼市调控不断升级,房产中介还能翻身吗?
  9. 【面试官一定会问的几题】视觉过关挑战赛 - 附源码
  10. 遗传算法之路径规划matlab代码(栅格地图)含详细注释
  11. Virtualbox如何配置Linux的网络连接
  12. mysql中的resultt框没有了_mysql中的zentao.zt_config表格消失了
  13. 徐州好玩实用的微信小程序
  14. e光的matlab,【e光嫩肤的效果怎么样】_功效_作用-大众养生网
  15. 四旋翼与固定翼的空中对接降落
  16. 怎样调用通达信l2行情接口?
  17. Java web产品开发经验分享
  18. TensorFlow入门教程(21)分心驾驶行为检测
  19. 深澜系统服务器架构,与深澜服务器配合做portal认证配置
  20. lisp 相贯线展开_一个画两管相接相贯线的程序 - AutoLISP/Visual LISP 编程技术 - CAD论坛 - 明经CAD社区 - Powered by Discuz!...

热门文章

  1. 微信小程序数据操作(增、删、改、查),id为随机数
  2. java实现正态分布(钟形曲线)
  3. 弘辽科技:网店商家遇到客户投诉该如何正确处理?
  4. 数学建模之悬链线方程
  5. “李逵”还是“李鬼”,傻傻分不清楚
  6. CNAS/CMA?什么是认证认可?
  7. Lombok,@Data - Generating equals/hashCode implementation but without a call to superclass
  8. android 中的二维码生成与去除白边
  9. 在线少儿英语平台权威评测 冠军花落vipJr
  10. [iOS]一行代码集成空白页面占位图(基于runtime+MJRefresh思想)