`
ctrain
  • 浏览: 133425 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论
收藏列表
标题 标签 来源
身份证校验 Js完美验证15/18身份证
var vcity={ 11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",
        	21:"辽宁",22:"吉林",23:"黑龙江",31:"上海",32:"江苏",
        	33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",
        	42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",
        	51:"四川",52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃",
        	63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"
           };

checkCard = function()
{
	var card = document.getElementById('card_no').value;
	//是否为空
	if(card === '')
	{
		alert('请输入身份证号,身份证号不能为空');
		document.getElementById('card_no').focus;
		return false;
	}
	//校验长度,类型
	if(isCardNo(card) === false)
	{
		alert('您输入的身份证号码不正确,请重新输入');
		document.getElementById('card_no').focus;
		return false;
	}
	//检查省份
	if(checkProvince(card) === false)
	{
		alert('您输入的身份证号码不正确,请重新输入');
		document.getElementById('card_no').focus;
		return false;
	}
	//校验生日
	if(checkBirthday(card) === false)
	{
		alert('您输入的身份证号码生日不正确,请重新输入');
		document.getElementById('card_no').focus();
		return false;
	}
	//检验位的检测
	if(checkParity(card) === false)
	{
		alert('您的身份证校验位不正确,请重新输入');
		document.getElementById('card_no').focus();
		return false;
	}
	alert('OK');
	return true;
};


//检查号码是否符合规范,包括长度,类型
isCardNo = function(card)
{
	//身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X
	var reg = /(^\d{15}$)|(^\d{17}(\d|X)$)/;
	if(reg.test(card) === false)
	{
		return false;
	}

	return true;
};

//取身份证前两位,校验省份
checkProvince = function(card)
{
	var province = card.substr(0,2);
	if(vcity[province] == undefined)
	{
		return false;
	}
	return true;
};

//检查生日是否正确
checkBirthday = function(card)
{
	var len = card.length;
	//身份证15位时,次序为省(3位)市(3位)年(2位)月(2位)日(2位)校验位(3位),皆为数字
	if(len == '15')
	{
		var re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/; 
		var arr_data = card.match(re_fifteen);
		var year = arr_data[2];
		var month = arr_data[3];
		var day = arr_data[4];
		var birthday = new Date('19'+year+'/'+month+'/'+day);
		return verifyBirthday('19'+year,month,day,birthday);
	}
	//身份证18位时,次序为省(3位)市(3位)年(4位)月(2位)日(2位)校验位(4位),校验位末尾可能为X
	if(len == '18')
	{
		var re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/;
		var arr_data = card.match(re_eighteen);
		var year = arr_data[2];
		var month = arr_data[3];
		var day = arr_data[4];
		var birthday = new Date(year+'/'+month+'/'+day);
		return verifyBirthday(year,month,day,birthday);
	}
	return false;
};

//校验日期
verifyBirthday = function(year,month,day,birthday)
{
	var now = new Date();
	var now_year = now.getFullYear();
	//年月日是否合理
	if(birthday.getFullYear() == year && (birthday.getMonth() + 1) == month && birthday.getDate() == day)
	{
		//判断年份的范围(3岁到100岁之间)
		var time = now_year - year;
		if(time >= 3 && time <= 100)
		{
			return true;
		}
		return false;
	}
	return false;
};

//校验位的检测
checkParity = function(card)
{
	//15位转18位
	card = changeFivteenToEighteen(card);
	var len = card.length;
	if(len == '18')
	{
		var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); 
		var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); 
		var cardTemp = 0, i, valnum; 
		for(i = 0; i < 17; i ++) 
		{ 
			cardTemp += card.substr(i, 1) * arrInt[i]; 
		} 
		valnum = arrCh[cardTemp % 11]; 
		if (valnum == card.substr(17, 1)) 
		{
			return true;
		}
		return false;
	}
	return false;
};

//15位转18位身份证号
changeFivteenToEighteen = function(card)
{
	if(card.length == '15')
	{
		var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); 
		var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); 
		var cardTemp = 0, i;   
		card = card.substr(0, 6) + '19' + card.substr(6, card.length - 6);
		for(i = 0; i < 17; i ++) 
		{ 
			cardTemp += card.substr(i, 1) * arrInt[i]; 
		} 
		card += arrCh[cardTemp % 11]; 
		return card;
	}
	return card;
};
long类型读取
针对数据字典的LONG类型字段如何查询?由于where条件中long类型 的字段上不可使用任何函数,所以需要将long转换成clob来迂回一下
以dba_view这个作为 例子
方法如下:
create table clob_dba_views (owner varchar2(30),view_name varchar2(30),text clob);
insert into clob_dba_views select owner,view_name,to_lob(text) from dba_views;
commit;
select owner,view_name from clob_dba_views where dbms_lob.instr(text,'sss')>0;
xml配置文件读取
package com.pafa.check;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.nutz.lang.Files;
import org.nutz.lang.Xmls;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class RoleChecker {

	private static final Log log = Logs.getLog(RoleChecker.class);

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {

			Map<String,String> serMap = new HashMap<String,String>();
			Map<String,String> secMap = new HashMap<String,String>();
			//Map<String,String> bizMap = new HashMap<String,String>();
			
			Document um_service_doc = Xmls.xml(Files.findFile("D:\\umservice_ELIS_LAS.xml"));
			Document um_security_doc = Xmls.xml(Files.findFile("D:\\um-security-acl-ELIS_LAS.xml"));
			Document user_biz_doc = Xmls.xml(Files.findFile("D:\\user-biz-logic.xml"));
			//Document user_biz_doc = Xmls.xml(Files.findFile("D:\\user-biz-logic.xml"));

			XPathFactory factory = XPathFactory.newInstance();
			XPath xpath = factory.newXPath();
			XPathExpression expr = xpath.compile("//umservice/roles/role/cn/text()");
			
			XPathFactory factory1 = XPathFactory.newInstance();
			XPath xpath1 = factory1.newXPath();
			XPathExpression expr1 = xpath1.compile("//policy/security-constraint/auth-constraint/role-name/text()");
			//XPathExpression expr2 = xpath.compile("//beans/bean/onstructor-arg/map/entry/key/text()");

			Object result = expr.evaluate(um_service_doc, XPathConstants.NODESET);
			NodeList nodes = (NodeList) result;
			for (int i = 0; i < nodes.getLength(); i++) {
				String roleName = nodes.item(i).getNodeValue();
				serMap.put(roleName.toUpperCase(), roleName);
				log.info("[umservice_ELIS_LAS]"+roleName);
			}
			log.info("\n");
			log.info("------------------------------------------");
			log.info("\n");
			
			Object result1 = expr1.evaluate(um_security_doc, XPathConstants.NODESET);
			NodeList nodes1 = (NodeList) result1;
			for (int i = 0; i < nodes1.getLength(); i++) {
				String roleName = nodes1.item(i).getNodeValue();
				secMap.put(roleName.toUpperCase(), roleName);
				log.info("[um-security-acl-ELIS_LAS]"+roleName);
			}
			
			/*Object result2 = expr2.evaluate(user_biz_doc, XPathConstants.NODESET);
			NodeList nodes2 = (NodeList) result2;
			for (int i = 0; i < nodes2.getLength(); i++) {
				String roleName = nodes2.item(i).getNodeValue();
				secMap.put(roleName.toUpperCase(), roleName);
				log.info("[user-biz-logic]"+roleName);
			}*/
			
			log.info("【start】开始比较umservice_ELIS_LAS与um-security-acl-ELIS_LAS中角色名称");
			Set<String> roleSet = serMap.keySet();
			Iterator<String> it = roleSet.iterator();
			while(it.hasNext()){
				String key = it.next();
				String roleName_ser = serMap.get(key);
				String roleName_sec = secMap.get(key);
				if(roleName_sec == null){
					log.info("【err1】[umservice_ELIS_LAS]角色<"+roleName_ser+">在[um-security-acl-ELIS_LAS]中没有找到对应角色");
				} else if(roleName_ser.endsWith(roleName_sec)){
					log.info("【ok】[umservice_ELIS_LAS]角色<"+roleName_ser+">与[um-security-acl-ELIS_LAS]中角色名称一致");
				} else{
					log.info("【err2】[umservice_ELIS_LAS]角色<"+roleName_ser+">与[um-security-acl-ELIS_LAS]中角色<"+roleName_sec+">名称不一致");
				}
				
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
人人可用的项目管理Office秘笈
http://roll.sohu.com/20120222/n335553092.shtml
如何将Project中的任务传送到Outlook中去
http://www.mypm.net/blog/user1/highfar/archives/2010/52299.html

http://bbs.weiphone.com/read-htm-tid-6332964.html

http://bbs.21manager.com/dispbbs-204515-1.html

安装和配置用于 Outlook 的 Project 2007 外接程序(内网不可用)

源文档 <http://technet.microsoft.com/zh-cn/library/cc197276(v=office.12).aspx> 
人人可用的项目管理Office秘笈

源文档 <http://roll.sohu.com/20120222/n335553092.shtml> 

做好项目管理之1——使用outlook和onenote进行事项管理

源文档 <http://blog.sina.com.cn/s/blog_4b678be4010107hb.html> 
如何更加有效地管理时间和任务:你真的会用Outlook吗?

源文档 <http://www.cnblogs.com/chenxizhang/archive/2008/10/07/1305456.html> 
项目管理书籍推荐 
http://thinkingstone.iteye.com/blog/405391
东吴相对论书籍
http://www.docin.com/p-358154319.html
Oracle学习路径与规划
Oracle入门书籍介绍
http://www.eygle.com/archives/2006/08/oracle_fundbook_recommand.html

http://www.eygle.com/archives/2008/11/become_dba_quickly.html

Oracle学习路径与规划
http://www.eygle.com/archives/2008/11/oracle_internals_preface.html


oracle

http://www.eygle.com/blog/our_dba_life.html
替换DEL(127)字符 字符替换
rowStr = rowStr.replaceAll("\\x7F", "");
Word制作业内引用
Word制作业内引用
http://jingyan.baidu.com/album/3c343ff72b24ca0d377963bd.html?picindex=1
js日期校验&js获取月份第一天最后一天
<script>
var date = "102013";
var a = /^((0[1-9])|(1[0-2]))\d{4}$/;
var res = a.test(date);
alert(res);
/**
var date_ = new Date();
var year = date_.getYear() > 1900 ? date_.getYear() : 1900 + date_.getYear();
var month = date_.getMonth() + 1;
var firstdate =  month + '/01/' + year
//var month_first = formatDate(parseDate(firstdate),"yyyy-MM-dd")+" 00:00:00";

var day = new Date(year,month,0);    
var lastdate =  month + '/' + day.getDate() + "/" + year;
//var month_last = formatDate(parseDate(lastdate),"yyyy-MM-dd")+" 24:00:00";
alert(firstdate);//alert(month_first);
alert(lastdate);//alert(month_last);
*/
</script>
js日期比较
//String regex1 = "^[1|2][0-9]{3}(0[1-9]|(1[0-2]))(([0-2][0-9])|(3[0-1]))$";//"yyyyMMdd"
String regex = "^[1|2][0-9]{3}-(0[1-9]|(1[0-2]))-(([0-2][0-9])|(3[0-1]))$";//"yyyy-MM-dd"


	
先全选表格,点击右键在“设置单元格格式”里的保护中去掉保护前的对号,然后在工具-保护-保护工作表里,去掉所有的对号,只在“选定未锁定的单元格”和“编辑对象”中打勾就可以了,记住加上密码!
qq:48104901

对不起,应该是“点击右键在“设置单元格格式”里的保护中去掉锁定前的对号!


日期比较:
var myDate = new Date();
var year = ( myDate.getYear() < 1900 ) ? ( 1900 + myDate.getYear() ) : myDate.getYear();
var now_tmp = year +"-"+(myDate.getMonth()+1)+"-"+myDate.getDate();
var d1 = $.fn.datebox.defaults.parser(now_tmp);
var d2 = $.fn.datebox.defaults.parser(begin_owned_time);
if(d1 < d2){
	errMsg += "享受政策性住房,享受政策性住房时间不能大于当前日期;<br/>";
	isPass = false;
}
关注博客
easyui相关笔记:
http://www.mikel.cn
EasyUI的Tab组件添加与关闭 js tab hide show
如下为自己写的动态显示隐藏代码的片段:
var tab1 = $('#tabsid').tabs('getTab', '统发退款').panel('options').tab;
var tab2 = $('#tabsid').tabs('getTab', '个人退款').panel('options').tab;
if (selectType == "1") {
	tab1.hide();
	$('#tabsid').tabs('select', '个人退款');
	tab2.show();
} else if (selectType == "2") {
	tab1.show();
	$('#tabsid').tabs('select', '统发退款');
	tab2.hide();
}
===========================================================

以下摘自网络:

项目中需要根据不同的属性设置EasyUI的Tab组件的某页的动态关闭和显示,tab标签的代码如下:
<div id='tt' class="easyui-tabs" cache="false">
 <div title='基本信息'></div>
 <div title='联系方式'></div>
 <div id='product' title='产品'></div>
</div>
需要根据用户的类型来显示和隐藏产品tab页,开始以为直接根据状态直接$(‘#product’).hide();就可以了,可是试过后发现不行,于是查看了easyUI的tab组件的文档,发现有close方法可以关闭tab页,于是改写成:
if(data.state=='1') $('#tt').tabs('close','产品');
可是,如果data.state==2则需要打开tabs可是没有open方法,tab已经被关闭了,没办法只好创建一个了,代码如下:
if ($('#tt').tabs('exists', title)) {
    //$('#tt').tabs('select', title);
    reloadTab(title,url);
} else {
    $('#tt').tabs('add', {
        title: title,
        href:url
    });
}
关于String垃圾回收
String 的垃圾回收不需将String置为Null
form 转成map方便获取前台传递的值
public Map<String, FileItem>  getReqMap(MainContext maincontext) throws FileUploadException {
	HttpServletRequest request = maincontext.getRequest();
	long MAX_SIZE = 50 * 1024 * 1024;// 允许上传的文件大小50M
	// 实例化一个硬盘文件工厂,用来配置上传组件ServletFileUpload
	DiskFileItemFactory factory = new DiskFileItemFactory();
	factory.setSizeThreshold(4096);// 设置上传文件时用于临时存放文件的内存大小,这里是4K.多于的部分将临时存在硬盘
	ServletFileUpload fileUpload = new ServletFileUpload(factory);
	fileUpload.setSizeMax(MAX_SIZE);
	fileUpload.setHeaderEncoding("gbk");
	maincontext.getResponse().setContentType("text/html;charset=gbk");
	List fileList = null; // 从request得到所有上传域的列表
	fileList = fileUpload.parseRequest(request);

	Map<String,FileItem> reqMap = new HashMap<String,FileItem>();
	FileItem fileItem = null;
	for(int i=0; i<fileList.size(); i++) {
		fileItem = (FileItem) fileList.get(i);
		String fileName = fileItem.getFieldName();
		if(fileName != null && !"".equals(fileName)) {
			reqMap.put(fileName, fileItem);
		}
	}

	return reqMap;
}
序列跨用户查询
 create or replace synonym seq_haf_unitinfo  for housedbo.seq_haf_unitinfo;
HttpUrlConnection httpurlconnection
HttpUrlConnection在weblogic容易出现转码导致url连接错误,可改为HttpClient来实现。
java7位随机数
public String generate7Random() {
	int firstNum = 1 + new java.util.Random().nextInt(9);
	return Math.round((firstNum + Math.random()) * 1000000) + "";
}
js replaceALl replaceall
String.prototype.replaceAll = function(s1,s2) {return this.replace(new RegExp(s1,"gm"),s2);}
js replaceALl js replace JS中实现replaceAll的方法
<script type="text/javascript">
String.prototype.replaceAll = function(reallyDo, replaceWith, ignoreCase) {
    if (!RegExp.prototype.isPrototypeOf(reallyDo)) {
        return this.replace(new RegExp(reallyDo, (ignoreCase ? "gi": "g")), replaceWith);
    } else {
        return this.replace(reallyDo, replaceWith);
    }
}
</script>
球两个字符串包含字符的并集 并集
/**
     * 求两个字符串所包含字符的并集 wk 2012.05.19
     */
    public static String getStringUion(String str1,String str2){
		char[] a = str1.toCharArray();
		char[] b = str2.toCharArray();
		Set<Character> set = new HashSet<Character>();
		for(char _a:a){
			set.add(_a);
		}
		for(char _b:b){
			set.add(_b);
		}
		StringBuilder result = new StringBuilder();
		Iterator<Character> iterator = set.iterator();
		while(iterator.hasNext()){
			result.append(iterator.next());
		}
		return result.toString();
	}
java日期比较与日期加减 日期比较, 日期加减
public static void main(String[] args) {

		//比较日期大小
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

		Date date = null;
		try {
			//比较大小测试
			String d1 = "2012-12-20";
			date = format.parse(d1);
			c1.setTime(date);

			String d2 = "2013-03-20";
			date = format.parse(d2);
			c2.setTime(date);
			
			int res = c1.compareTo(c2);
			if(res == 0){
				System.out.println("c1 等于 c2");
			}else if(res < 0){
				System.out.println("c1 小于 c2");
			}else if(res > 0){
				System.out.println("c1 大于 c2");
			}
			
			//日期加减
			c1.add(Calendar.DAY_OF_MONTH, 1);
			System.out.println("2012-12-20 的明天是:" + format.format(c1.getTime()));
			
			c2.add(Calendar.DAY_OF_MONTH, -1);
			System.out.println("2013-03-20 的昨天是:" + format.format(c2.getTime()));
			
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
恢复trigger Quartz任务监控管理 (1)
//获取到Scheduler
Scheduler scheduler = ...;//(Scheduler)springContext.getBean("quartzScheduler");
//通过trigger name和trigger group得到SimpleTrigger 
SimpleTrigger trigger = (SimpleTrigger)scheduler.getTrigger("52f071d3-eebb-4308-abeb-9ce8ec58aba4", "DEFAULT");
//重新设置Trigger己经触发的次数
int timesTriggered = trigger.getTimesTriggered();
trigger.setTimesTriggered(timesTriggered > 0 ? timesTriggered -1 : 0);

//可选,重新设置开始触发时间
//trigger.setStartTime(startTime);
//可选,重新设置下次触发时间
//trigger.setNextFireTime(nextFireTime);
//等等,还有许多可选配置可以重新设置

//调用rescheduleJob重新调度tirgger
scheduler.rescheduleJob(trigger.getName(), trigger.getGroup(), trigger);
限制单个文件上传大小 java 限制附件上传大小
package cn.agrael.fileupload;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import cn.agrael.io.UploadResource;
import cn.agrael.util.Null;
import cn.agrael.util.tuple.FiveTuple;
import cn.agrael.util.tuple.Tuple;

/**
 * Multipart的解析类,用作 http 的 Multipart 提交数据的解析。
 * @author <a href="mailto:agraellee@gmail.com">AgraelLee</a>
 *
 */
public class SimpleMultipartParse {

	private static final byte CR = '\r';

	private static final byte NL = '\n';

	private static final byte DASH = '-';
	
	private static final String CONTENT_DISPOSITION = "content-disposition: ";
	
	static final NullOutputStream NULL_OUTPUT_STREAM = new NullOutputStream();

	private byte[] boundary;
	
	private byte[] tmpBoundaryBuffer;
	
	private int bufferLength = 4068;
	
	private String headerEncoding;
	
	private String saveDir;
	
	private ReadLineInputStream stream;
	
	private Map<String, String[]> parameterMap = new HashMap<String, String[]>();
	
	private Map<String, UploadResource[]> uploadResourceMap = new HashMap<String, UploadResource[]>();
	
	public SimpleMultipartParse() {
		
	}
	
	public Map<String, String[]> getParameterMap() {
		return this.parameterMap;
	}

	public Map<String, UploadResource[]> getUploadResourceMap() {
		return this.uploadResourceMap;
	}

	public String getHeaderEncoding() {
		return this.headerEncoding;
	}

	public void setHeaderEncoding(String headerEncoding) {
		this.headerEncoding = headerEncoding;
	}
	
	public int getBufferLength() {
		return bufferLength;
	}

	public void setBufferLength(int bufferLength) {
		this.bufferLength = bufferLength;
	}

	public void parse(InputStream stream, String saveDir,
			long maxPostSize, long contentLength) throws MaxUploadSizeExceededException, MalformedStreamException,
			IOException {
		if (maxPostSize != 0) {
			if (contentLength != -1 && contentLength > maxPostSize) {
				throw new MaxUploadSizeExceededException(maxPostSize, contentLength);
			}
		}
		this.stream = new ReadLineInputStream(stream);
		this.saveDir = saveDir;
		// 得到分割线
		this.boundary = readBoundary();
		this.tmpBoundaryBuffer = new byte[this.boundary.length];
		// 开始解析分割线分开的每一个块
		boolean notEnd = true;
		while (notEnd) {
			FiveTuple<String, String, String, OutputStream, File> tuple = parseHeader(readHeader());
			String name = tuple.getFirst();
			String fileName = tuple.getSecond();
			OutputStream out = tuple.getFourth();
			try {
				while (notEnd) {
					int b = this.stream.read();
					if (b == CR) {
						// 如果是 \r,则取下一个字节判断是否\n,如果是\r\n,则读取分隔符长度的字节判断下一个是否分隔符,如果是,则表示该块解析完成
						int next = this.stream.read();
						if (next == NL) {
							int index = this.stream.read(this.tmpBoundaryBuffer);
							if (index == -1) {
								throw new MalformedStreamException();
							}
							// 读取分隔符长度的字节判断下一个是否分隔符
							if (Arrays.equals(this.boundary, this.tmpBoundaryBuffer)) {
								// 如果是分隔符,则判断是接下来的2个字节
								int x = this.stream.read();
								int y = this.stream.read();
								if (x == CR && y == NL) {
									// 为 \r\n
									break;
								}
								if (x == DASH && y == DASH) {
									// 为结束符号 --
									notEnd = false;
									break;
								}
								// 其他情况
								out.write(b);
								out.write(next);
								out.write(this.tmpBoundaryBuffer);
								out.write(x);
								out.write(y);
								continue;
							} else {
								// 如果不为下一个分隔符,则把\r\n和读取判断的字节全部写入流
								out.write(b);
								out.write(next);
								out.write(this.tmpBoundaryBuffer);
								continue;
							}
						} else {
							// 如果不为\r\n,则写入流中
							out.write(b);
							out.write(next);
							continue;
						}
					}
					out.write(b);
				}
			} finally {
				if (out != null) {
					out.flush();
					out.close();
				}
			}
			if (fileName == null) {
				// 文本域
				addParameter(this.parameterMap, name, byteArrayOutToString((ByteArrayOutputStream)out, this.headerEncoding));
			} else if (isFile(fileName)) {
				// 文件域,如果fileName也是文件域,但是是没数据的文件域,所以不处理
				if (this.headerEncoding == null) {
					addUploadResourceParameter(this.uploadResourceMap, name, new UploadResource(tuple.getFifth(), tuple.getThird(), fileName));
				} else {
					addUploadResourceParameter(this.uploadResourceMap, name, new UploadResource(tuple.getFifth(), tuple.getThird(), fileName, this.headerEncoding));
				}
			}
		}
		this.boundary = null;
		this.tmpBoundaryBuffer = null;
	}
	
	static String byteArrayOutToString(ByteArrayOutputStream out, String encoding) throws IOException {
		if (encoding != null) {
			try {
				return out.toString(encoding);
			} catch (UnsupportedEncodingException e) {
				return out.toString();
			}
		}
		return out.toString();
	}
	
	static void addParameter(Map<String, String[]> parameterMap, String key, String value) {
		String[] oldValues = parameterMap.get(key);
		if (oldValues != null) {
			String[] newValues = new String[oldValues.length + 1];
			System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
			newValues[oldValues.length] = value;
			parameterMap.put(key, newValues);
		} else {
			parameterMap.put(key, new String[]{value});
		}
	}
	
	static void addUploadResourceParameter(Map<String, UploadResource[]> parameterMap, String key, UploadResource value) {
		UploadResource[] oldValues = parameterMap.get(key);
		if (oldValues != null) {
			UploadResource[] newValues = new UploadResource[oldValues.length + 1];
			System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
			newValues[oldValues.length] = value;
			parameterMap.put(key, newValues);
		} else {
			parameterMap.put(key, new UploadResource[]{value});
		}
	}
	
	protected FiveTuple<String, String, String, OutputStream, File> parseHeader(String header) throws IOException {
		String origHeader = header;
		header = origHeader.toLowerCase();
		int start = header.indexOf(CONTENT_DISPOSITION);
	    int end = header.indexOf(";");
	    if (start == -1 || end == -1) {
	      throw new MalformedStreamException("错误的 content-disposition: " + origHeader);
	    }
	    String disposition = header.substring(start + CONTENT_DISPOSITION.length(), end);
	    if (!disposition.equals("form-data")) {
	      throw new MalformedStreamException("错误的 content-disposition: " + disposition);
	    }
	    // 解析 name
	    start = header.indexOf("name=\"", end);
	    end = header.indexOf("\"", start + 7);
	    int startOffset = 6;
	    if (start == -1 || end == -1) {
	      // 如果没有找到可能是因为有些浏览器可能不会加双引号则解析没有双引号的name
	      start = header.indexOf("name=", end);
	      end = header.indexOf(";", start + 6);
	      if (start == -1) {
	        throw new MalformedStreamException("错误的 content-disposition: " + origHeader);
	      }
	      else if (end == -1) {
	        end = header.length();
	      }
	      startOffset = 5;
	    }
	    String name = origHeader.substring(start + startOffset, end);
	    // 解析 fileName
	    String fileName = null;
	    File tmpFile = null;
	    start = header.indexOf("filename=\"", end + 2);
	    end = header.indexOf("\"", start + 10);
	    OutputStream out;
	    String contentType = null;
	    if (start != -1 && end != -1) {
			fileName = origHeader.substring(start + 10, end);
			int slash = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));
			if (slash > -1) {
				fileName = fileName.substring(slash + 1);
			}
			// 解析Content-Type
			contentType = origHeader.substring(end);
			if ("".equals(contentType)) {
				contentType = null;
			} else {
				try {
					contentType = contentType.substring(15);
				} catch (IndexOutOfBoundsException e) {
					contentType = null;
				}
			}
			if (isFile(fileName)) {
				// 创建临时文件的输出流
				while (true) {
					tmpFile = new File(this.saveDir, UUID.randomUUID().toString() + ".tmp");
					if (!tmpFile.exists()) {
						tmpFile.createNewFile();
						tmpFile.deleteOnExit();
						break;
					}
				}
				out = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferLength);
			} else {
				out = NULL_OUTPUT_STREAM;
			}
	    } else {
	    	out = new ByteArrayOutputStream(128);
	    }
	    return Tuple.tuple(name, fileName, contentType, out, tmpFile);
	}
	
	private boolean isFile(String fileName) {
		return !"".equals(fileName);
	}
	
	protected byte[] readBoundary() throws IOException {
		ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(64);
		readLine(bytesOut, new byte[50]);
		return bytesOut.toByteArray();
	}
	
	private ByteArrayOutputStream readLine() throws IOException {
		ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(64);
		readLine(bytesOut, new byte[this.bufferLength]);
		return bytesOut;
	} 
	
	protected void readLine(ByteArrayOutputStream bytesOut, byte[] buffer) throws IOException {
		// 循环读取,知道到达流末尾或者行结束
		for (int i = 0; (i = this.stream.readLine(buffer, 0, buffer.length)) != -1; ) {
			// 判断是否一个行结束
			if (i < buffer.length) {
				// 如果读取的字节数小于缓冲大小,则行结束跳出循环。
				bytesOut.write(buffer, 0, i - 2);
				break;
			}
			if (buffer.length > 1 && i == buffer.length && buffer[i - 2] == CR && buffer[i - 1] == NL) {
				// 如果读取字节数和缓冲大小相等时,末尾是\r\n则是行结束则跳出循环
				bytesOut.write(buffer, 0, i - 2);
				break;
			}
			bytesOut.write(buffer);
		}
	} 
	
	protected String readHeader() throws IOException {
		ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(256);
		for (byte[] tmp; ; ) {
			tmp = readLine().toByteArray();
			String lineStr = new String(tmp);
			if ("".equals(lineStr)) {
				break;
			}
			bytesOut.write(tmp);
		}
		return byteArrayOutToString(bytesOut, this.headerEncoding);
	}
	
	static class ReadLineInputStream extends InputStream {
		
		private InputStream inputStream;
		
		ReadLineInputStream(InputStream inputStream) {
			this.inputStream = inputStream;
	    }

	    public int readLine(byte b[], int off, int len) throws IOException {
			if (len <= 0) {
				return 0;
			}
			int count = 0;
			int c;
			do {
				if ((c = read()) == -1) {
					break;
				}
				b[off++] = (byte) c;
				count++;
			} while (c != NL && count != len);
			return count <= 0 ? -1 : count;
	    }

	    @Override
		public int available() throws IOException {
			return this.inputStream.available();
		}

		@Override
		public void close() throws IOException {
			this.inputStream.close();
		}

		@Override
		public boolean equals(Object obj) {
			return this.inputStream.equals(obj);
		}

		@Override
		public int hashCode() {
			return this.inputStream.hashCode();
		}

		@Override
		public void mark(int readlimit) {
			this.inputStream.mark(readlimit);
		}

		@Override
		public boolean markSupported() {
			return this.inputStream.markSupported();
		}

		public int read() throws IOException {
			return this.inputStream.read();
		}

		@Override
		public int read(byte[] b, int off, int len) throws IOException {
			return this.inputStream.read(b, off, len);
		}

		@Override
		public int read(byte[] b) throws IOException {
			return this.inputStream.read(b);
		}

		@Override
		public void reset() throws IOException {
			this.inputStream.reset();
		}

		@Override
		public long skip(long n) throws IOException {
			return this.inputStream.skip(n);
		}

		@Override
		public String toString() {
			return this.inputStream.toString();
		}
	    
	    
	}
	
	static class NullOutputStream extends OutputStream implements Null {
		
		@Override
		public void close() throws IOException {
		}

		@Override
		public void flush() throws IOException {
		}

		@Override
		public void write(byte[] b, int off, int len) throws IOException {
		}

		@Override
		public void write(byte[] b) throws IOException {
		}

		@Override
		public void write(int b) throws IOException {
			
		}
		
	}
}
Global site tag (gtag.js) - Google Analytics