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());
        }
    }
}

 

posted @ 2019-09-08 15:39  风吹屁股凉冰冰  阅读(354)  评论(0编辑  收藏  举报