// 文件路径 D:\ApacheServer\web_java\HelloWorld\src\com\test\TestServletForm.java
package com.test;
import java.io.File;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.filefilter.SuffixFileFilter;
public class TestServletForm {
public void testfun(HttpServletRequest request){
// 检测是 GET 和 x-www-form-urlencode POST 还是 multipart/form-data POST 方式
if (!ServletFileUpload.isMultipartContent(request)) {
// 提交的表单类型为GET 或者 x-www-form-urlencoded 方式的 POST
getOrFormUrlencoded(request);
}else {
// 提交的表单类型为 multipart/form-data 的 POST
formData(request);
}
}
// 自建方法,用来处理 GET URL 或者 application/x-www-form-urlencoded 方式的 POST
public void getOrFormUrlencoded(HttpServletRequest request){
// getParameter,getParameterNames 只能获取 get 参数(POST 请求里也能用 getParameter 获取 GET 参数)或者编码格式为 application/x-www-form-urlencoded 的 post 数据,无法获取 multipart/form-data 的 post 数据
// application/x-www-form-urlencoded 传的 post 数据实际和 get 方式一样,都是格式化成 参数1=值1&参数2=值2&参数3=值3&... ,区别是 get 参数在 url 中,post 参数在请求体里。
String name_val = request.getParameter("name");
System.out.println("表单名 : name 单一值为 : " + name_val);
// getParameterNames() 方法获取所有提交的表单参数名。该方法返回一个枚举对象,包含未指定顺序的参数名
Enumeration paramNames = request.getParameterNames();
// hasMoreElements() 循环遍历判断该枚举是否有更多元素,指针每次往后移一位
while(paramNames.hasMoreElements()) {
// nextElement() 每次获取该枚举一个元素,指针每次往后移一位
String paramName = (String)paramNames.nextElement();
// 根据参数名获取对应参数值,但不知道该参数名对应单个值还是多个值(复选框即是多个表单同名,不同值,与PHP不同JAVA相同复选框名后面不用加中括号 [] ),所以用数组接收
String paramValues[] = request.getParameterValues(paramName);
// 读取参数值的数据
if (paramValues.length == 1) { // 该参数名对应单一参数值
// 参数值为 paramValues[0]
String paramValue = paramValues[0];
if (paramValue.length() > 0) { // 判断该参数值有实际字符串内容
System.out.println("表单名 : " + paramName + "单一值为 : " + paramValue);
}
} else {
// 读取多个值的数据
for(int i=0; i < paramValues.length; i++) {
// 值为 paramValues[i]
System.out.println("多重参数名 : " + paramName + "多重id值 : "+i+"为 : " + paramValues[i]);
}
}
}
}
// 自建方法,用来处理 multipart/form-data 方式的 POST
// 获取 form-data 类型 post 数据依赖于 FileUpload,下载地址 http://commons.apache.org/proper/commons-fileupload/ 这里用到的是 FileUpload 1.4 选择 Binaries->commons-fileupload-1.4-bin.zip
// FileUpload 依赖于 Commons IO,下载地址 http://commons.apache.org/proper/commons-io/ 这里用到的是 Commons IO 2.6 选择 Binaries->commons-io-2.6-bin.zip
// 将下载的压缩包内的 commons-io-2.6.jar 和 commons-fileupload-1.4.jar 解压缩到 D:\ApacheServer\web_java\HelloWorld\WebContent\WEB-INF\lib 中。环境变量 CLASSPATH 补充 ";D:\ApacheServer\web_java\HelloWorld\WebContent\WEB-INF\lib\commons-io-2.6.jar;D:\ApacheServer\web_java\HelloWorld\WebContent\WEB-INF\lib\commons-fileupload-1.4.jar;" 。在eclipase左侧目录中(WEB-INF\lib)选中该jar包右键 Build Path -> Add to Build Path
public void formData(HttpServletRequest request){
try {
// 创建磁盘文件项目工厂(form-data方式POST获取参数必须用的不管有无上传文件),可设置限制上传文件的临时存储目录等
DiskFileItemFactory factory = new DiskFileItemFactory();
// 可有可无,setSizeThreshold方法判断post数据(包括上传文件及表单数据)的大小(以字节为单位的int值,大于该值则post数据以临时文件形式存在磁盘,小于等于此值则存在内存中),如果从没有调用该方法设置此临界值,将会采用系统默认值10KB。对应的getSizeThreshold() 方法用来获取此临界值。
//factory.setSizeThreshold(1024 * 1024 * 3); // 3MB
// 可有可无,设置当上传数据大于 setSizeThreshold 设置的值时,临时文件在磁盘上的存放目录。当从没有此方法设置临时文件存储目录时,采用系统默认的临时文件路径 Tomcat 系统默认临时目录为 tomcat安装目录/temp/,默认的临时文件路径可通过 System.getProperty("java.io.tmpdir");查看
//factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
// 通过文件工厂对象创建上传对象,可设置 post 文件最大上传大小,请求数据最大值(包含文件和表单数据)等
ServletFileUpload upload = new ServletFileUpload(factory);
// 可有可无,设置上传的单个文件的最大字节数为100M
//upload.setFileSizeMax(1024 * 1024 * 100);
// 可有可无,设置整个表单的最大字节数为1G (包含文件和表单数据)
//upload.setSizeMax(1024 * 1024 * 1024);
// 可有可无,中文处理,解决上传数据的中文乱码
//upload.setHeaderEncoding("UTF-8");
// 构造路径存储上传的文件,request.getServletContext().getRealPath("./") 获取的路径 为 WEB-INF 文件夹父级目录,即项目根目录路径,这里路径为 D:\ApacheServer\web_java\HelloWorld\WebContent\\upload\00125943U-0.jpg。这里WebContent为实际项目运行根目录
String uploadPath = request.getServletContext().getRealPath("./") + "upload";
// 如果目录不存在则创建,目录同样只能一级一级创建,不能一次创建多级
File uploadDir = new File( uploadPath );
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
// List类传泛型 FileItem 则其创建对象内元素都变为 FileItem 类型
// 将用户请求传给设置好参数的上传对象,返回一个数组
List<FileItem> item_list = upload.parseRequest(request);
// 创建 param_map 保存提交表单的键值对
Map param_map = new HashMap();
// 假设有未知个数同表单名的复选框表单提交信息,用 testCheckBox 存该复选框选中的值
Map testCheckBox = new HashMap();
if (item_list != null && item_list.size() > 0) {
// 遍历上传的表单元素
for(FileItem fileItem : item_list){
// fileItem.getFieldName() 表单参数名
String fieldName = fileItem.getFieldName();
// fileItem.getString("UTF-8") 获取表单参数的值,或者上传文件的文本内容
String fieldVal = fileItem.getString("UTF-8"); // 如果页面编码是 UTF-8 的
// 处理在表单中的字段
if (fileItem.isFormField()) {
System.out.println("表单参数名 : " + fieldName + " 参数值为 : " + fieldVal);
// 当表单名为 testCheckBox 时,将其不确定个数的多个值存到 Map 对象中
if(fieldName.equals("testCheckBox")) {
testCheckBox.put(testCheckBox.size(), fieldVal);
}
// 把post参数以键值对形式重新存到 param_map 列表中。复选框的话最后一个选中的同名值会覆盖之前的值
param_map.put(fieldName, fieldVal);
}
// 处理表单中上传文件,这里上传文件的表单名任意都可上传
if (!fileItem.isFormField()) {
// ===============上传文件
// 获取上传的文件名(含扩展名),fileItem.getName()只能获取上传文件的完整名,不能获取其他post表单参数值
String fileName = fileItem.getName();
// 拼接将文件保存本地完整路径及文件+扩展名。File.separator 表示目录分割斜杠
String filePath = uploadPath + File.separator + fileName;
// 将合成的完整路径文件名 filePath 放入 File 对象中,File 对象代表磁盘中实际存在的文件和目录
File saveFile = new File(filePath);
// 限制上传文件扩展名
String suffix_limit[] = {".html", ".jpg", ".jsp"};
SuffixFileFilter filter = new SuffixFileFilter(suffix_limit);
boolean flag = filter.accept(saveFile);
if(!flag) {
System.out.println("上传文件类型不符表单名 : " + fieldName + ",文件名为 : " + fileName);
//return;
}
// 将该上传文件按指定路径保存文件到硬盘
fileItem.write(saveFile);
request.setAttribute("message", "文件上传成功!");
}
}
}
// 可以使用 param_map.get 获取表单参数值了
String name_val = (String) param_map.get("name");
System.out.println("表单name的值 : " + name_val);
// 遍历获取复选框的 Map 对象里每个值
for(int i = 0;i<testCheckBox.size();i++) {
System.out.println("复选框i : " + i + "对应值 : " + (String) testCheckBox.get(i));
}
} catch (FileUploadException fex) {
fex.printStackTrace();
} catch (Exception ex) {
request.setAttribute("message", "错误信息: " + ex.getMessage());
}
}
}