package utils; import java.io.*; import java.util.*; import javax.servlet.*; public class MultipartFormReader { private final int READY = 0; private final int FILENAME = 1; private final int NAME = 2; private final int BINDATA = 3; private final int TXTDATA = 4; public MultipartFormReader() {;} /** * Parses the ServletInputStream of encoding multipart/form-data and separates it into name value pairs. The name-value pairs * are stored in the map argument. There are a couple of this to be aware of. This class is not a replacement for * the ServletRequest class but augments it. It should only be used in the case where the client is issuing an HTTP POST request * and the form-encoding is multipart/form-data. * *

In the event the HTTP POST request contains binary data --for example, when someone * wants to upload data to your servlet-- it is stored as a byte array. You can retrieve the binary data by calling the get method * on the map object you passed in as a parameter. *

i.e.: byte[] uploadedImage = (byte[]) map.get( "fieldname" );

* There is no limit to the amount of binary data that can be uploaded and retrieved. * *

For those situations where the HTTP POST request contains list data (i.e. checkboxes, multiple selection lists), the list data * is stored in a java.util.List object. This is equivalent to the javax.servlet.ServletRequest's * public String[] getParameterValues( java.lang.String ) method. *

i.e.: java.util.List checkboxItems = (java.util.List)map.get( "fieldname" ); * * @param request A ServletRequest object. * @param map The Map will be populated with the name value pairs of the HTML form's content. * It works pretty much like the HttpServletRequest class except it can handle multipart/form-data. */ public void read( ServletRequest request, Map map ) throws IOException { byte[] bytes = new byte[ 2048 ]; int state = 0; int eof = 0; /* Get the separator for this request's form data. It is necessary for parsing this request's form data. */ String boundary = request.getContentType(); int pos = boundary.indexOf( "=" ); boundary = boundary.substring( pos + 1 ); boundary = "--" + boundary; String fieldName = null; String fieldValue = null; ServletInputStream sStream = request.getInputStream(); ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream(); eof = sStream.readLine( bytes, 0, 2048 ); map.clear(); state = 0; while( -1 != eof ) { String filter = new String( bytes, 0, eof ); if( filter.startsWith( boundary ) ) { state = READY; if( null != fieldName ) { if( null != fieldValue ) { Object o = map.get( fieldName ); Object val = fieldValue.substring( 0, fieldValue.length() - 2 ); if( null == o ) map.put( fieldName, val ); else { if( o instanceof List ) ((List)o).add( val ); else { List list = new ArrayList(); list.add( o ); list.add( val ); map.put( fieldName, list ); } } } else if( dataBuffer.size() > 2 ) { map.put( fieldName, dataBuffer.toByteArray() ); } fieldName = null; fieldValue = null; dataBuffer.reset(); } } else if( filter.startsWith( "Content-Disposition: form-data" ) && state == READY ) { StringTokenizer tokenizer = new StringTokenizer( filter, ";=\"" ); while( tokenizer.hasMoreTokens() ) { String token = tokenizer.nextToken().trim(); if( token.startsWith( "name" ) ) { fieldName = tokenizer.nextToken().trim(); state = NAME; } else if( token.startsWith( "filename" ) ) { state = FILENAME; break; } } } else if( filter.equals( "\r\n" ) && state == FILENAME ) state = BINDATA; else if( filter.equals("\r\n" ) && state == NAME ) state = TXTDATA; else if( state == TXTDATA ) fieldValue = fieldValue == null ? filter : fieldValue + filter; else if( state == BINDATA ) dataBuffer.write( bytes, 0, eof ); eof = sStream.readLine( bytes, 0, 2048 ); }// Parsing stops here. The Map should now contain all of the form's data. sStream.close(); } /** * A utility method that saves you the trouble of having to create a Map object and passing it to the other read method. * * @param request The ServletRequest object * * @return A java.util.HashMap containing the name-value pairs of the HTTP POST's form data */ public HashMap read( ServletRequest request ) throws IOException { HashMap hash = new HashMap(); this.read( request, hash ); return hash; } }