在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. 用clock()统计代码的执行时间(C语言)
  2. ||x||的错误理解
  3. 日本Blogger专用电脑
  4. 一款不错的网站压力测试工具webbench
  5. C# MVC 自定义ActionResult实现EXCEL下载
  6. Mysql 新增用户可访问指定数据库所有权限
  7. bug 执行nrm 报错internal/validators.js:121 throw new ERR_INVALID_ARG_TYPE(name, ‘string‘, value);
  8. 前端压缩图片,前端压缩图片后转换为base64.
  9. php设置自动关机开机,设置电脑自动开机关机方法介绍
  10. MySQL设置字符编码
  11. matlab李雅普诺夫吸引子,matlab计算Rossler吸引子的李雅普诺夫指数
  12. django官方文档3.0学习笔记 03
  13. 计算机平面设计考试试题及答案,最新国家开放大学电大专科《计算机平面设计(1)》网络课形考任务1及任务2答案...
  14. Linux平台基于v4l2开发免驱摄像头-输出为Opencv Mat
  15. 云的基本概念(公有云、私有云、混合云, IaaS、PaaS、SaaS)
  16. 红米 10X和红米10X Pro 的区别
  17. 你选择了你的记忆,和生活。
  18. Powershell 5.1中Shift + Insert无法粘贴解决
  19. mysql floor 不准确_MYSQL的floor出现报错如何解决
  20. 程序员多赚20k的接私活必备网站

热门文章

  1. 《遗传算法原理及应用》笔记—进化计算
  2. 通用BLE射频芯片实现无线功能
  3. 期刊卷号期号什么意思
  4. mysql临时密码不能用,自动生成临时密码后无法访问MySQL
  5. 2021年安全员-B证免费试题及安全员-B证证考试
  6. jango model.obejcts.filter 查询指定字段
  7. 【华为认证】快速了解IP地址(教你查看自己的IP地址)
  8. 学习java的一些书单推荐
  9. html5 css3图标制作,CSS3 生成ICO图标
  10. 小功率调频发射机设计