content: package com.alimama.web.adhoc;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.OutputStreamWriter;
  import java.io.UnsupportedEncodingException;
  import java.util.HashMap;
  import java.util.HashSet;
  
  import javax.servlet.ServletInputStream;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import org.apache.hadoop.fs.FSDataOutputStream;
  import org.apache.log4j.Logger;
  import org.mortbay.log.Log;
  
  import com.alimama.web.ByteBuffer;
  
  
  
  public class Upload {
  	private static Logger LOG = Logger.getLogger(Upload.class);
  
  	private static int BUFFER_LEN=10240;
  	private static int HEADER_SIZE=102400;
  	char[]  buffer = new char[BUFFER_LEN];
      
  	//----boundary----
      private char[] m_boundary = new char[HEADER_SIZE];
      private int m_boundary_length=0;
      private boolean foundBoundary = false;
      
      //----for file split---
      int boundarySkipLen=0;
      
      //----for header read----
      private boolean foundHeader=false;
      //----header info-----
      private String dataHeader = new String();
      private String fieldName = new String();
      private String fileName = new String();
      private String fileExt = new String();
      private String filePathName = new String();
      private String contentType = new String();
      private String contentDisp = new String();
      private String typeMIME = new String();
      private String subTypeMIME = new String();
      private boolean isFile = false;
      
      
  	private void resetHeader()
  	{
  		 this.foundHeader=false;
  		 this.boundarySkipLen=0;
  
  	}
  	
  	
  	private int setBoundary(int readBytes,int i)
  	{
  		for(; !foundBoundary && i<readBytes; i++)
          {
              if(buffer[i] == 13)
              {
                  foundBoundary = true;
                  
                  char[] newboundary=new char[m_boundary_length];
                  for(int j=0;j<m_boundary_length;j++)
                  {
                  	newboundary[j]=m_boundary[j];
                  }
                  m_boundary=newboundary;
                  break;
              }
              else
              {
              	int currindex=m_boundary_length;
              	m_boundary_length++;
                  m_boundary[currindex]=buffer[i];
              }
          }
  		return i;
  	}
  	
  	private static char[] headerSplit={13,42,13};
  	
  	
  	private char[] splitbuffer=new char[0];
  	private boolean setHearder(int readBytes,int i,String charset) throws UnsupportedEncodingException
  	{
  		int leftdata=readBytes-i;
  		int lastlen=splitbuffer.length;
  		char[] tmpbyte=new char[lastlen+leftdata];
  		for(int j=0;j<lastlen;j++)
  		{
  			tmpbyte[j]=splitbuffer[j];
  		}
  		for(int j=0;j<leftdata;j++)
  		{
  			tmpbyte[j+lastlen]=buffer[j+i];
  		}
  		
  		ByteSplit split=this.readUntil(tmpbyte, headerSplit,true);
  		splitbuffer=split.left;
  		foundHeader=split.isfullcut;
   	    if(foundHeader)
   	    {
  				dataHeader = new String(split.read, 0, split.read.length);
  				LOG.info("@@@@@@@dataHeader:" + dataHeader + "@@@@"
  						+ new String(m_boundary, 0, m_boundary_length));
  
  				isFile = dataHeader.indexOf("filename") > 0;
  				fieldName = getDataFieldValue(dataHeader, "name");
  				if (isFile) {
  					filePathName = getDataFieldValue(dataHeader, "filename");
  					fileName = getFileName(filePathName);
  					fileExt = getFileExt(fileName);
  					contentType = getContentType(dataHeader);
  					contentDisp = getContentDisp(dataHeader);
  					typeMIME = getTypeMIME(contentType);
  					subTypeMIME = getSubTypeMIME(contentType);
  					LOG.info("@@@@@@@file:" + fieldName + "," + filePathName
  							+ "," + fileName);
  
  				}
   	    }
   	    
   	    return foundHeader;
  	}
  	
  	private boolean setHeadVal(int readBytes,int i,String charset,OutputStreamWriter out,HashMap<String,String> params) throws IOException
  	{
  		int leftdata=readBytes-i;
  		int lastlen=splitbuffer.length;
  		char[] tmpbyte=new char[lastlen+leftdata];
  		for(int j=0;j<lastlen;j++)
  		{
  			tmpbyte[j]=splitbuffer[j];
  		}
  		for(int j=0;j<leftdata;j++)
  		{
  			tmpbyte[j+lastlen]=buffer[j+i];
  		}
  		
  		ByteSplit split=this.readUntil(tmpbyte, m_boundary,false);
  		splitbuffer=split.left;
  		foundHeader=split.isfullcut;
  		
  		
  		for(int j=0;j<split.read.length;j++)
  		{
  			writebuff.append(split.read[j]);
  		}
  		
  		if(writebuff.size()>10240&&isFile)
          {
          	out.write(writebuff.toArray(),0,writebuff.size());
          	writebuff=new ByteBuffer(10752);
          }
  		
  		if(split.isfullcut)
  		{
   			this.skip(out, writebuff, charset, params);
   			writebuff=new ByteBuffer(10752);
  
  		}
  		return split.isfullcut;
  	}
  	
  	
      ByteBuffer writebuff=new ByteBuffer(10752);
      
  	public void mergerTo(HttpServletRequest request, HttpServletResponse response,String charset,OutputStreamWriter out,HashMap<String,String> params) throws IOException
  	{
  //		int totalBytes  = request.getContentLength();
  //        ServletInputStream in=request.getInputStream();
          InputStreamReader in=new InputStreamReader(request.getInputStream(), "gbk") ;
  //	    OutputStreamWriter osw = new OutputStreamWriter(System.out, "UTF-8");
  //	    osw.
  
          int readBytes = 0;
          
          this.resetHeader();
          boolean isReadHeader=true;
          
          
          int index=0;
          int totalRead=0;
          while(true)
          {
  //        	int size=totalBytes - totalRead;
              readBytes = in.read(buffer, 0, BUFFER_LEN);
              if(index++%10000==0)
              {
              	Log.info("total read="+totalRead);
              }
              
              if(readBytes<0)
              {
              	break;
              }
              
              totalRead += readBytes;
              
              int i=0;
              i=this.setBoundary(readBytes, i);
              if(i>=readBytes)
              {
              	continue;
              }
              
              boolean isloop=true;
              
              while(isloop)
              {
      			isloop=false;
  	            if(isReadHeader)
  	        	{
  	        		if(this.setHearder(readBytes, i,charset))
  	        		{
  	        			isReadHeader=false;
  	        			isloop=true;
  	        		}
  	        	}else{
  	        		if(this.setHeadVal( readBytes, i, charset, out, params))
  	        		{
  	        			isReadHeader=true;
  	        			isloop=true;
  	        		}
  	        	}
  	            i=readBytes;
              }
              
          }
          
          if(this.splitbuffer.length>0)
          {
  	    	for(int j=0;j<this.splitbuffer.length;j++)
  			{
  				writebuff.append(splitbuffer[j]);
  			}
          }
          
          
  
          if(writebuff.size()>0&&!keys.contains(fieldName))
          {
          	if(isFile)
          	{
          		out.write(writebuff.toArray(),0,writebuff.size());
          	}else{
          		String val=new String(writebuff.toArray(),0,writebuff.size()).replaceAll("^[\r|\n]*", "").replaceAll("[\r|\n]*$", "");
  				params.put(fieldName, val);
      			LOG.info("@@@@@@@keyval_final:"+fieldName+"="+val);
          	}
          	writebuff=new ByteBuffer(10752);
          }
          
          
  
          
  	}
  	
  	HashSet<String> keys=new HashSet<String>(); 
  	
  	private void skip(OutputStreamWriter out, ByteBuffer writebuff,String charset,HashMap<String,String> params) throws IOException
  	{
  		keys.add(fieldName);
  		if(this.isFile)
  		{
  			out.write(writebuff.toArray(),0,writebuff.size());
  		}else{
  			String val=new String(writebuff.toArray(),0,writebuff.size()).replaceAll("^[\r|\n]*", "").replaceAll("[\r|\n]*$", "");
  			params.put(fieldName, val);
  			LOG.info("@@@@@@@keyval:"+fieldName+"="+val);
  
  		}
  
  		this.resetHeader();
  	}
  	
  	private String getFileExt(String fileName)
  	    {
  	        String value = new String();
  	        int start = 0;
  	        int end = 0;
  	        if(fileName == null)
  	            return null;
  	        start = fileName.lastIndexOf(46) + 1;
  	        end = fileName.length();
  	        value = fileName.substring(start, end);
  	        if(fileName.lastIndexOf(46) > 0)
  	            return value;
  	        else
  	            return "";
  	    }
  
  	    private String getContentType(String dataHeader)
  	    {
  	        String token = new String();
  	        String value = new String();
  	        int start = 0;
  	        int end = 0;
  	        token = "Content-Type:";
  	        start = dataHeader.indexOf(token) + token.length();
  	        if(start != -1)
  	        {
  	            end = dataHeader.length();
  	            value = dataHeader.substring(start, end);
  	        }
  	        return value;
  	    }
  
  	    private String getTypeMIME(String ContentType)
  	    {
  	        int pos = 0;
  	        pos = ContentType.indexOf("/");
  	        if(pos != -1)
  	            return ContentType.substring(1, pos);
  	        else
  	            return ContentType;
  	    }
  
  	    private String getSubTypeMIME(String ContentType)
  	    {
  	        int start = 0;
  	        int end = 0;
  	        start = ContentType.indexOf("/") + 1;
  	        if(start != -1)
  	        {
  	            end = ContentType.length();
  	            return ContentType.substring(start, end);
  	        } else
  	        {
  	            return ContentType;
  	        }
  	    }
  
  	    private String getContentDisp(String dataHeader)
  	    {
  	        String value = new String();
  	        int start = 0;
  	        int end = 0;
  	        start = dataHeader.indexOf(":") + 1;
  	        end = dataHeader.indexOf(";");
  	        value = dataHeader.substring(start, end);
  	        return value;
  	    }
  	
  	 private String getDataFieldValue(String dataHeader, String fieldName)
  	    {
  	        String token = new String();
  	        String value = new String();
  	        int pos = 0;
  	        int i = 0;
  	        int start = 0;
  	        int end = 0;
  	        token = String.valueOf((new StringBuffer(String.valueOf(fieldName))).append("=").append('"'));
  	        pos = dataHeader.indexOf(token);
  	        if(pos > 0)
  	        {
  	            i = pos + token.length();
  	            start = i;
  	            token = "\"";
  	            end = dataHeader.indexOf(token, i);
  	            if(start > 0 && end > 0)
  	                value = dataHeader.substring(start, end);
  	        }
  	        return value;
  	    }
  	 
  	 private String getFileName(String filePathName)
  	    {
  	        int pos = 0;
  	        pos = filePathName.lastIndexOf(47);
  	        if(pos != -1)
  	            return filePathName.substring(pos + 1, filePathName.length());
  	        pos = filePathName.lastIndexOf(92);
  	        if(pos != -1)
  	            return filePathName.substring(pos + 1, filePathName.length());
  	        else
  	            return filePathName;
  	    }
  	 
  	 
  
  	    private static class ByteSplit{
  	    	public boolean isfullcut;
  			public char[] read;
  	    	public char[] left;
  	    	public ByteSplit(boolean isfullcut, char[] read, char[] left) {
  				super();
  				this.isfullcut = isfullcut;
  				this.read = read;
  				this.left = left;
  			}
  	    	
  	    }
  	    private ByteSplit readUntil(char[] buffer,char[] search,boolean fuzzle) {
  	        final int len = buffer.length;
  	        int matpos=len;
  	        boolean isfound=false;
  	        for (int i = 0; i < len; ++i) {
  		   		int leftlen=len-i;
  	        	if(this.ismatch(buffer, search,i,0,Math.min(search.length, leftlen),fuzzle))
  	      		{
  	        		isfound=true;
  	    	   		matpos=i;
  	    	   		break;
  	      		}
  	        }
  	        
  	        boolean isfullcut=isfound&&(len-matpos>=search.length);
  	        char[] read=new char[matpos];
  	        for(int i=0;i<matpos;i++)
  	        {
  	        	read[i]=buffer[i];
  	        }
  	        int offset=matpos;
  	        if(isfullcut)
  	        {
  	        	offset+=search.length;
  	        }
  	        
  	        int leftlen=len-offset;
  	        leftlen=leftlen>0?leftlen:0;
  	        
  	        char[] left=new char[leftlen];
  	        for(int i=0;i<leftlen;i++)
  	        {
  	        	left[i]=buffer[i+offset];
  
  	        }
  	        
  	        return new ByteSplit(isfullcut, read, left);
  	      }
  	    
  	    private boolean ismatch(char[] buffer,char[] search,int offset,int start,int end,boolean fuzzle)
  	    {
  	    	 boolean isallMatch=true;
  	   		 for(int j=start;j<end;j++)
  	   		 {
  	   			 if(!this.ismatch(buffer[j+offset], search[j],fuzzle))
  	   			 {
  	   				 isallMatch=false;
  	   				 break;
  	   			 }
  	   		 }
  	   		 
  	   		 return isallMatch;
  	    }
  	    
  	    private boolean ismatch(char a,char mat,boolean fuzzle){
  	    	if(fuzzle)
  	    	{
  	    		return mat==42||a==mat;
  	    	}
  	    	return a==mat;
  	    }
  }
  