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

📄 multirequest.java

📁 培训考试系统代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package com.huawei.icd30.agt.util;

import java.io.*;
import java.util.*;
import javax.servlet.http.*;

/**
 * <p>&nbsp;&nbsp;&nbsp; 该类用于在Servlet或JSP中处理以“multipart/form-data”
 * 格式提交的请求数据。通过传入一个HttpServletRequest对象构造该对象,然后即可用
 * 该对象取得请求中的普通参数及上传文件。如果请求不是该格式,构造时将抛出
 * IllegalArgumentException异常。
 * </p>
 * <p>&nbsp;&nbsp;&nbsp; 由于普通请求对象HttpServletRequest不能处理该编码类型的
 * 请求,即使没有上传文件,也不能通过getParameter()等方法得到参数。该类的一部分
 * 功能模仿HttpServletRequest,提供同名的方法用来获取请求中所带的参数。包括:
 * getPamameterNames()、getPamameter()、getPamameterValues()。如果某个参数代表的
 * 是一个上传文件,则参数值是指该文件的文件名。另外提供upload()方法用于将一个上
 * 传文件的内容写入一个输出流,可选指定文件大小限制;如果有多个上传文件,则应该
 * 按照文件上传的顺序,依次调用upload()来保存。可以通过getFilename()方法用来得到
 * 一个需上传的文件的文件名,也可以根据文件参数的参数名通过getParameter()来获得
 * 文件名。upload()方法使用输出流来接收数据,因此不限制必须用文件形式保存,可根
 * 据具体应用以各种方式保存或处理上传数据。upload()的第二个参数可选,用来定义最
 * 大上传文件长度,若不定义这个参数则没有限制。若上传的文件长度超过设定限额,则
 * upload()方法在写入正好最大限额那么多数据后返回-1。当upload()因文件超大而返回
 * 时,可以再次调用upload()方法,将继续上传剩余部分。如果文件长度小于或等于最大
 * 限额,返回文件真实长度。若用户在输入页面的文件输入框里随便输入一个不存在的文
 * 件,upload()在上传时会返回长度0,调用者可根据返回值的不同做相应处理。
 * </p>
 * <p>&nbsp;&nbsp;&nbsp; <b>注意:</b>有一个重要的限制是多个文件只能按参数次序依
 * 次上传,不能颠倒;并且在一个文件完成上传之前将不能得到在这个文件数据之后的参
 * 数,因为该类为支持大文件上传,并不保存上传的数据。因此比较好的解决方案是依参
 * 数次序处理,或者先上传文件,再处理普通参数(普通参数会保存)。为防止受限制,最
 * 好将文件域放在HTML表单的后面。另外由于HTTP协议的特点,在上传文件之前最好不要
 * 向客户端输出页面,因为浏览器在上传完数据之前不会接收页面数据,写页面的操作可
 * 能被阻塞。若必须这样做可将页面缓冲设置足够大:在JSP中如下设置缓冲:
 * &lt;%@ page buffer="16k" %&gt;。
 * </p>
 * <p>&nbsp;&nbsp;&nbsp; 代码举例:在JSP页面或Servlet的doPost方法中写如下代码即
 * 可实现将请求中带的全部文件上传至upload目录:
 * <pre>
 * ......                                                                  <br>
 * MultiRequest mr = new MultiRequest(request);                            <br>
 * while (mr.getFilename()!=null && mr.getFilename().length()>0) {         <br>
 *   OutputStream os = new FileOutputStream("upload/"+mr.getFilename());   <br>
 *   mr.upload(os);                                                        <br>
 *   os.close();                                                           <br>
 * }                                                                       <br>
 * ......
 * </pre>
 * </p>
 * <p>&nbsp;&nbsp;&nbsp; 本类功能在以下环境测试通过:<br>
 * 服务器:Resin1.3、Tomcat3.1、Apache+Tomcat3.1;JDK1.2.2、1.3.1、1.4beta <br>
 * 浏览器:NT4.0+IE4.0、Win98+IE5.0、Win98+Netscape4.5、SunOS5.7+Netscape6 <br>
 * 该类使用了Java2平台的集合类,在JDK1.1及1.0下编译和运行需要集合类扩展包。本程
 * 序只有这一个文件,不依赖于其他内容,可单独编译,编译时需要servlet接口。
 * </p>
 * <p>&nbsp;&nbsp;&nbsp; 如果在使用过程中发现Bug,或有什么建议请发邮件至
 * <a href="mailto:ldv@huawei.com">ldv@huawei.com</a> 谢谢。
 * </p>
 * @author 李大伟
 * @version 1.0
 * @修改人: ICD业务V3.0 B组-外包-黎新朝
 * @修改记录: 增加取上传文件的全路径的方法.
 */
public class MultiRequest {

  /** 从ServletRequest得到的输入流 */
  private InputStream requestStream;

  /** 保存参数值,文件类型的参数值是其在客户端的文件名(不包括路径)。*/
  private HashMap parameters = new HashMap();

  /** 保存可以上传的文件的文件名,若当前位置不是一个文件则为空。*/
  private String filename;

  /** 保存可以上传的文件的文件全名(带路径),若当前位置不是一个文件则为空。by 黎新朝*/
  private String fileFullName;

  /** 缓冲区长度。2048是实践值,再大并不会提高性能。*/
  private final int BUFFER_SIZE = 2048;

  /** 流解析过程中的使用缓冲区。*/
  private byte[] buffer = new byte[BUFFER_SIZE];

  /** 协议头和正文的分隔符。*/
  private final byte[] HEAD_END = new byte[]{0x0d,0x0a,0x0d,0x0a};

  /** 各参数域的分隔符。*/
  private byte[] boundary;

  /** 输入流已经结束。*/
  private boolean inputFinished = false;

  /** 缓冲区中保存的有效数据长度。*/
  private int dataLength = 2;


  /** request 使用的字符集。--黎新朝增加,用于支持中文。
  *   影响MultiRequest(HttpServletRequest request)和readString(byte[] endFlag)
  */
  private String charset;


  /**
   * 用一般请求对象构造一个能处理multipart/form-data格式请求的对象。由于普通请求
   * 对象HttpServletRequest不能处理该编码类型的请求,即使没有上传文件,也不能通
   * 过getParameter()等方法得到参数。因此需要用该对象同名的方法来替代。另外提供
   * upload()方法用于上传文件。其它功能请还是使用原来的HttpServletRequest对象,
   * 例如得到协议头中的属性、获取Servlet上下文等。
   * @param request JSP内部变量request,或Servlet的doPost()方法传入的请求对象。
   * @throws IOException 读取请求数据流出现异常时。
   * @exception IllegalArgumentException 解析数据出错:如请求数据格式不是
   *            multipart/form-data格式,或找不到应该存在的协议头等。
   */
  public MultiRequest(HttpServletRequest request) throws IOException {

    //缓冲区中先放入回车换行
    buffer[0]=(byte)'\r';
    buffer[1]=(byte)'\n';

    //保存request使用的字符编码 -- add by 黎新朝
    this.charset = request.getCharacterEncoding() ;
    requestStream = request.getInputStream();
    String contentType = request.getContentType();
    if (contentType == null)
      throw new IllegalArgumentException("Can not determine content type");
    int i = contentType.indexOf("boundary=");
    if (i<=0) //该请求不是multipart/form-data格式
      throw new IllegalArgumentException("Not multipart/form-data format");
    try {
      boundary = ("\r\n--"+contentType.substring(i+9)).getBytes("ASCII");
    } catch (Exception ex) {
      throw new IllegalArgumentException("Can not find boundary: " + ex);
    }
    while (parseNext()); //解析普通参数,直到流结束或遇到该上传文件。
  }

  /**
   * 根据参数名取得参数值。若当前有文件需要上传,则该文件后面的参数将不能获得,
   * (当前需要上传的文件的参数值可以获得,就是其文件名),若没有文件需要上传了则
   * 取得的参数就是完整的了。如果有多个同名参数,该方法只返回第一个参数值,可以
   * 用getParameterValues()方法获得所有同名参数的参数值数组。
   * @param paramName 参数名。
   * @return 参数值。如果参数不存在,或者在尚未上传的文件之后,返回null。
   * @
   */
  public String getParameter(String paramName) {
    List values = (List) parameters.get(paramName);
    if (values ==null)
      return null;
    else
      return (String) values.get(0);
  }

  /**
   * 取得多值参数的所有参数值数组。若当前有文件需要上传,则该文件后面的参数将不
   * 能获得,(当前需要上传的文件的参数值可以获得,就是其文件名),若没有文件需要
   * 上传了则取得的参数就是完整的了。
   * @param paramName 参数名。
   * @return 若参数存在,返回参数值数组;若参数不存在返回null。
   */
  public String[] getParameterValues(String paramName) {
    List values = (List) parameters.get(paramName);
    if (values == null)
      return null;
    else
      return (String[]) values.toArray(new String[0]);
  }

  /**
   * 取得当前已经获得的所有参数名。若当前有文件需要上传,则该文件后面的参数将不
   * 能获得,(当前需要上传的文件的参数值可以获得,就是其文件名),若没有文件需要
   * 上传了则取得的参数就是完整的了。
   * @return 参数名枚举。
   */
  public Enumeration getPamameterNames() {
    return Collections.enumeration(parameters.keySet());
  }

  /**
   * 取得当前已经准备好上传的文件的文件名。如果明确知道文件域的名字(多数情况是这
   * 样),也可以通过getParameter()方法获得文件名。该方法一般用在不考虑传来的参数
   * 和文件有哪些,一股脑成批处理。同时也可用来判断当前是否应该进行上传操作若返
   * 回null,那一定是已经没有文件需要上传了。
   * @return 准备好上传的文件的文件名,若当前没有文件可上传则返回null。
   */
  public String getFilename() {
    return filename;
  }

  /**
   * 取得当前已经准备好上传的文件的全路径名。如果明确知道文件域的名字(多数情况是这
   * 样),也可以通过getParameter()方法获得文件名。该方法一般用在不考虑传来的参数
   * 和文件有哪些,一股脑成批处理。同时也可用来判断当前是否应该进行上传操作若返
   * 回null,那一定是已经没有文件需要上传了。
   * @return 准备好上传的文件的文件名,若当前没有文件可上传则返回null。
   * @add by 黎新朝.
   */
  public String getFullFilename() {
    return fileFullName ;
  }

  /**
   * 将上传的一个文件的内容写入到一个输出流中。输出流的打开和关闭和缓冲清洗
   * (flush)由调用者负责。该方法对上传文件的大小没有限制。
   * @param os 数据输出的目的地。
   * @return 成功返回文件大小,出错返回小于0的错误号,其中流结束返回-2。
   * @throws IOException 从请求中读数据或往输出流里写数据时出现异常。
   */
  public int upload(OutputStream os) throws IOException {
    return upload(os,Integer.MAX_VALUE);
  }

⌨️ 快捷键说明

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