Servlet 表单及上传文件
// 文件路径 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()); } } }