⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multipartrequest.java

📁 雷霆论坛是用J2EE技术开发的功能强大、扩展性强、易于定制
💻 JAVA
字号:
package lightningboard.util;

import java.util.Hashtable;
import java.util.Enumeration;
import java.io.File;
import java.io.IOException;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

import javax.servlet.ServletRequest;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;


public class MultiPartRequest{

  private File dir;
  private File file;
  private int maxSize;
  private Hashtable params = new Hashtable();
  private ServletRequest request;

  public Hashtable getParameters() {
    return params;
  }
  public String getParameter( String name ) {
    try {
      String param = (String)params.get( name );
      return param;
    }
    catch( Exception e ) {
      return null;
    }
  }

  public Enumeration getParameterNames() {
    return params.keys();
  }

  public String[] getParameterValues( String name ) {
    String param = (String)params.get( name );
    if( param != null ) {
      return new String[] {
        param
      };
    }
    return null;
  }

  public MultiPartRequest(HttpServletRequest request, String dir ,int maxSize)
         throws IOException {
    if( request == null ) {
      throw new IllegalArgumentException( "request can not be null" );
    }
    if( dir == null ) {
      throw new IllegalArgumentException( "dir can not be null" );
    }

    this.request     = request;
    this.dir     = new File(dir);
    this.maxSize = maxSize;

    // Check saveDirectory is truly a directory
    if( !this.dir.isDirectory() ) {
      throw new IllegalArgumentException( "Not a directory: " + dir );
    }

    // Check saveDirectory is writable
    if( !this.dir.canWrite() ) {
      throw new IllegalArgumentException( "Not writable: " + dir );
    }

    // Parse the request to get the parameters and files
    // Check the content type to make sure it's "multipart/form-data"
    String type = request.getContentType();
    if( type == null || !type.toLowerCase().startsWith( "multipart/form-data" ) ) {
      throw new IOException( "Content type isn't multipart/form-data" );
    }

    // Check the content length to prevent denial of service attacks
    int length = request.getContentLength();
    if( length > maxSize ) {
      throw new IOException( "Content length of " + length + " exceeds limit of " + maxSize );
    }

    // Get the boundary string
    int index = type.indexOf( "boundary=" );
    if( index == -1 ) {
      throw new IOException( "Separation boundary was not specified" );
    }
    String boundary = type.substring( index + 9 );
    boundary = "--" + boundary;

    // Construct the input stream
    InputStreamHandler in = new InputStreamHandler( request.getInputStream(), length );

    // Read the first line. should be boundary
    String line = in.readLine();
    if( line == null ) {
      throw new IOException( "Premature ending of form data" );
    }

    // Verify that the line is the boundary
    if( !line.startsWith( boundary ) ) {
      throw new IOException( "No leading boundary" );
    }

    // Loop over each part in the form data
    boolean done = false;
    while( !done ) {

      // Read the first line, should look like this:
      // content-disposition: form-data; name="field1"; filename="file1.txt"
      line = in.readLine();
      if( line == null ) {
        // No parts left, we're done
        done = true;
        continue;
      }

      // Convert the line to a lowercase string without the ending \r\n
      // Keep the original line for error messages and for variable names.
      String origline = line;
      line = origline.toLowerCase();

      // Get the content disposition, should be "form-data"
      int start = line.indexOf( "content-disposition: " );
      int end = line.indexOf( ";" );
      if( start == -1 || end == -1 ) {
        throw new IOException( "Content disposition corrupt: " + origline );
      }
      String disposition = line.substring( start + 21, end );
      if( !disposition.equals( "form-data" ) ) {
        throw new IOException( "Invalid content disposition: " + disposition );
      }

      // Get the field name
      start = line.indexOf( "name=\"", end ); // start at last semicolon
      end = line.indexOf( "\"", start + 7 ); // skip name=\"
      if( start == -1 || end == -1 ) {
        throw new IOException( "Content disposition corrupt: " + origline );
      }
      String name = origline.substring( start + 6, end );

      // Get the filename, if given
      String filename = null;
      start = line.indexOf( "filename=\"", end + 2 ); // start after name
      end = line.indexOf( "\"", start + 10 ); // skip filename=\"
      if( start != -1 && end != -1 ) { // note the !=
        filename = origline.substring( start + 10, end );

        // The filename may contain a full path.  Cut to just the filename.
        int slash = Math.max( filename.lastIndexOf( '/' ), filename.lastIndexOf( '\\' ) );
        if( slash > -1 ) {
          filename = filename.substring( slash + 1 ); // past last slash
        }
        if( filename.equals( "" ) ) {
          filename = "unknown"; // sanity check
        }
      }

      // Now onto the next line.  This will either be empty
      // or contain a Content-Type and then an empty line.
      line = in.readLine();
      if( line == null ) {
        // No parts left, we're done
        done = true;
        continue;
      }

      // Get the content type, or null if none specified
      if( line.toLowerCase().startsWith( "content-type" ) ) {
        line = in.readLine();
      }

      // Now, finally, we read the content (end after reading the boundary)
      if( filename == null ) {
        // This is a parameter
        String value = readParameter( in, boundary );
        params.put( name, value );
      }
      else {
        // This is a file
        saveFile( in, boundary, filename+".lb" );
        if( filename.equals( "unknown" ) ) {
          file = null;
        }
        else {
          file = new File( dir.toString() + File.separator + filename );
          params.put( name, file.getName() );
        }
      }
    }
  }

  /**
   * A method that reads a single part of the multipart request
   * that represents a file, and saves the file to the given directory.
   **/
  protected void saveFile( InputStreamHandler in, String boundary, String filename )
              throws IOException {
    File f = new File( dir + File.separator + filename );
    FileOutputStream fos = new FileOutputStream( f );
    BufferedOutputStream out = new BufferedOutputStream( fos, 8 * 1024 ); // 8K
    byte[] bbuf = new byte[100 * 1024]; // 100K
    int result;
    String line;

    // ServletInputStream.readLine() has the annoying habit of
    // adding a \r\n to the end of the last line.
    // Since we want a byte-for-byte transfer, we have to cut those chars.
    boolean rnflag = false;
    while( ( result = in.readLine( bbuf, 0, bbuf.length ) ) != -1 ) {
      // Check for boundary
      if( result > 2 && bbuf[0] == '-' && bbuf[1] == '-' ) { // quick pre-check
        line = new String( bbuf, 0, result, "ISO-8859-1" );
        if( line.startsWith( boundary ) ) {
          break;
        }
      }
      // Are we supposed to write \r\n for the last iteration?
      if( rnflag ) {
        out.write( '\r' );
        out.write( '\n' );
        rnflag = false;
      }
      // Write the buffer, postpone any ending \r\n
      if( result >= 2 && bbuf[result - 2] == '\r' && bbuf[result - 1] == '\n' ) {
        out.write( bbuf, 0, result - 2 ); // skip the last 2 chars
        rnflag = true; // make a note to write them on the next iteration
      }
      else {
        out.write( bbuf, 0, result );
      }
    }
    out.flush();
    out.close();
    fos.close();
  }

  /**
   * A method that reads a single part of the multipart request
   * that represents a parameter.
   * @param <b> in</b> the input stream
   * @param <b> boundary</b>  The delimiter string
   * @return <b>String</b> the parameter
   **/
  protected String readParameter( InputStreamHandler in, String boundary )
              throws IOException {
    StringBuffer sbuf = new StringBuffer();
    String line;
    while( ( line = in.readLine() ) != null ) {
      if( line.startsWith( boundary ) ) {
        break;
      }
      sbuf.append( line + "\r\n" ); // add the \r\n in case there are many lines
    }
    if( sbuf.length() == 0 ) {
      return null; // nothing read
    }
    sbuf.setLength( sbuf.length() - 2 ); // cut off the last line's \r\n
    return sbuf.toString(); // no URL decoding needed
  }
}


/**
 * A class to aid in reading multipart/form-data from a ServletInputStream.
 **/
class InputStreamHandler {

  // length of the stream
  int totalExpected;

  // total number of bytes read
  int totalRead = 0;

  // the reead buffer
  byte[] buf = new byte[8 * 1024];

  // input stream from the servlet request
  ServletInputStream in;

  /**
   * Reads the next line of input.  Returns null to indicate the end
   * of stream.
   * @return <b>String</b> the next line in the stream
   * @throws <b>IOException</b> If the next line could not be read
   **/
  public String readLine()
              throws IOException {
    StringBuffer sbuf = new StringBuffer();
    int result;
    String line;
    do {
      result = this.readLine( buf, 0, buf.length ); // this.readLine() does +=
      if( result != -1 ) {
        sbuf.append( new String( buf, 0, result, "ISO-8859-1" ) );
      }
    }while( result == buf.length ); // loop only if the buffer was filled
    if( sbuf.length() == 0 ) {
      return null; // nothing read, must be at the end of stream
    }
    sbuf.setLength( sbuf.length() - 2 ); // cut off the trailing \r\n
    return sbuf.toString();
  }

  /**
   * A pass-through to ServletInputStream.readLine() that keeps track
   * of how many bytes have been read and stops reading when the
   * Content-Length limit has been reached.
   * @param <b>b</b> the buffer to which the bytes are placed
   * @param <b>off</b> the offset at which reading should start
   * @param <b>len</b> max length of bytes to read
   **/
  public int readLine( byte b[], int off, int len )
              throws IOException {
    if( totalRead >= totalExpected ) {
      return -1;
    }
    else {
      int result = in.readLine( b, off, len );
      if( result > 0 ) {
        totalRead += result;
      }
      return result;
    }
  }

  public InputStreamHandler( ServletInputStream in, int totalExpected ) {
    this.in = in;
    this.totalExpected = totalExpected;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -