public Part readNextPart() throws IOException {
    // Make sure the last file was entirely read from the input
    if (lastFilePart != null) {
      lastFilePart.getInputStream().close();
      lastFilePart = null;
    }
    
    // Read the headers; they look like this (not all may be present):
    // Content-Disposition: form-data; name="field1"; filename="file1.txt"
    // Content-Type: type/subtype
    // Content-Transfer-Encoding: binary
    Vector headers = new Vector();

    String line = readLine();
    if (line == null) {
      // No parts left, we're done
      return null;
    }
    else if (line.length() == 0) {
      // IE4 on Mac sends an empty line at the end; treat that as the end.
      // Thanks to Daniel Lemire and Henri Tourigny for this fix.
      return null;
    }

    // Read the following header lines we hit an empty line
    // A line starting with whitespace is considered a continuation;
    // that requires a little special logic.  Thanks to Nic Ferrier for
    // identifying a good fix.
    while (line != null && line.length() > 0) {
      String nextLine = null;
      boolean getNextLine = true;
      while (getNextLine) {
        nextLine = readLine();
        if (nextLine != null
            && (nextLine.startsWith(" ")
      	  || nextLine.startsWith("\t"))) {
          line = line + nextLine;
        }
        else {
          getNextLine = false;
        }
      }
      // Add the line to the header list
      headers.addElement(line);
      line = nextLine;
    }

    // If we got a null above, it's the end
    if (line == null) {
      return null;
    }

    String name = null;
    String filename = null;
    String origname = null;
    String contentType = "text/plain";  // rfc1867 says this is the default

    Enumeration enu = headers.elements();
    while (enu.hasMoreElements()) {
      String headerline = (String) enu.nextElement();
      if (headerline.toLowerCase().startsWith("content-disposition:")) {
        // Parse the content-disposition line
        String[] dispInfo = extractDispositionInfo(headerline);
        // String disposition = dispInfo[0];  // not currently used
        name = dispInfo[1];
        filename = dispInfo[2];
        origname = dispInfo[3];
      }
      else if (headerline.toLowerCase().startsWith("content-type:")) {
        // Get the content type, or null if none specified
        String type = extractContentType(headerline);
        if (type != null) {
          contentType = type;
        }
      }
    }

    // Now, finally, we read the content (end after reading the boundary)
    if (filename == null) {
      // This is a parameter, add it to the vector of values
      // The encoding is needed to help parse the value
      return new ParamPart(name, in, boundary, encoding);
    }
    else {
      // This is a file
      if (filename.equals("")) {
        filename = null; // empty filename, probably an "empty" file param
      }
      lastFilePart = new FilePart(name, in, boundary,
                                  contentType, filename, origname);
      return lastFilePart;
    }
  }
public Part readNextPart ( ) throws IOException { if ( lastFilePart != null ) { lastFilePart . getInputStream ( ) . close ( ) ; lastFilePart = null ; } Vector headers = new Vector ( ) ; String line = readLine ( ) ; if ( line == null ) { return null ; } else if ( line . length ( ) == 0 ) { return null ; } while ( line != null && line . length ( ) > 0 ) { String nextLine = null ; boolean getNextLine = true ; while ( getNextLine ) { nextLine = readLine ( ) ; if ( nextLine != null && ( nextLine . startsWith ( " " ) || nextLine . startsWith ( "\t" ) ) ) { line = line + nextLine ; } else { getNextLine = false ; } } headers . addElement ( line ) ; line = nextLine ; } if ( line == null ) { return null ; } String name = null ; String filename = null ; String origname = null ; String contentType = "text/plain" ; Enumeration enu = headers . elements ( ) ; while ( enu . hasMoreElements ( ) ) { String headerline = ( String ) enu . nextElement ( ) ; if ( headerline . toLowerCase ( ) . startsWith ( "content-disposition:" ) ) { String [ ] dispInfo = extractDispositionInfo ( headerline ) ; name = dispInfo [ 1 ] ; filename = dispInfo [ 2 ] ; origname = dispInfo [ 3 ] ; } else if ( headerline . toLowerCase ( ) . startsWith ( "content-type:" ) ) { String type = extractContentType ( headerline ) ; if ( type != null ) { contentType = type ; } } } if ( filename == null ) { return new ParamPart ( name , in , boundary , encoding ) ; } else { if ( filename . equals ( "" ) ) { filename = null ; } lastFilePart = new FilePart ( name , in , boundary , contentType , filename , origname ) ; return lastFilePart ; } }
Read the next part arriving in the stream. Will be either a
<code>FilePart</code> or a <code>ParamPart</code>, or <code>null</code>
to indicate there are no more parts to read. The order of arrival
corresponds to the order of the form elements in the submitted form.

@return either a <code>FilePart</code>, a <code>ParamPart</code> or
<code>null</code> if there are no more parts to read.
@exception IOException	if an input or output exception has occurred.

@see FilePart
@see ParamPart