web过滤器中获取请求的参数(content-type:multipart/form-data)

来源:互联网 发布:今天的网络怎么了 编辑:程序博客网 时间:2024/05/29 19:40

http://www.cnblogs.com/springlight/p/6208908.html


web过滤器中获取请求的参数(content-type:multipart/form-data)

1.前言:

  1.1 在使用springMVC中,需要在过滤器中获取请求中的参数token,根据token判断请求是否合法;

  1.2 通过requst.getParameter(key)方法获得参数值;

    这种方法有缺陷:它只能获取  POST 提交方式中的Content-Type: application/x-www-form-urlencoded;

        HttpServletRequest request= (HttpServletRequest) req;        String param = request.getParameter("param");

 

    

2.问题:

  在一般的请求中,content-type为:application/x-www-form-urlencoded;在此种请求中,使用request.getParam(key)方法可以获取到key对应的属性值;

  因为最近涉及到文件的上传操作,上传文件的请求中content-type为:multipart/form-data;此种请求无法直接用request.getParam(key)获取对应的属性值,request中获取的属性值全部为空,无法正常获取;

 

3.问题描述:

  3.1 在web.xml中配置的过滤器

复制代码
  <filter>    <filter-name>requestFilter</filter-name>    <filter-class>util.web.RequestFilter</filter-class>  </filter>  <filter-mapping>    <filter-name>requestFilter</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping>
复制代码

 

  

  3.2  过滤器RequestFilter.java中获取token做匹配

    在如下过滤器中,上传文件中的content-type:multipart/form-data使用获取request.getParameter(key)无法获取相应的值。需要借助Spring框架中的CommonsMultipartResolver.resolveMultipart(HttpServletRequest request)将request转为MultipartHttpServletRequest,从而使用getParameter(key)方法获取指定的值;

    在将对象转化完成后,要将转化完成的对象赋值给过滤链中的request参数中,即如下代码中的  req = multiReq; 赋值完成很重要,否则在controller层中依旧无法获取其他参数。

 

    如果不需要再filter中获取请求中的值,则无需如下的操作,在请求经过springMVC框架后,自动会识别请求方式,如果是文件请求,会自动调用CommonsMultipartResolver.resolveMultipart(HttpServletRequest request)方法转化;

复制代码
package util.web;public class RequestFilter implements Filter {    protected FilterConfig filterConfig;    protected boolean filterEnabled;    protected int logLevel;    protected boolean needVCode;    protected List<String> noFilerList =null;    private CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();    public RequestFilter() {        this.filterConfig = null;        this.filterEnabled = true;        this.logLevel = -1;    }            @Override    public void destroy() {        // TODO Auto-generated method stub    }    @Override    public void doFilter(ServletRequest req, ServletResponse resp,            FilterChain chain) throws IOException, ServletException {        if(this.filterEnabled){            HttpServletRequest httpReq = (HttpServletRequest)req;            HttpServletResponse httpResp = (HttpServletResponse)resp;            String ctxPath = httpReq.getContextPath();             String requestUri = httpReq.getRequestURI();        //请求的全路径,比如:                     String uri = requestUri.substring(ctxPath.length());//全路径除去ctxPath            String tarUri = uri.trim();                String operatorHtmlModel = (httpReq.getHeader("referer")!=null?httpReq.getHeader("referer"):"").trim(); //获取当前页面的url,判断url是否是后台而url(后台的html就两个)            //不在过滤列表里的url请求,过滤列表包括t_sys_filter表中数据及visitor角色用户下的授权页面            if(!this.isInNoFilerList(tarUri)){                UserInfo uInfo = SessionUtil.getCurrentUser();                LoginAccount regAccout=SessionUtil.getCurrentPlateLoginAccount();                int type = 0 ;//平台账号未登录                if(operatorHtmlModel.endsWith(Const.LOGIN_TYPE_HTML[0])||operatorHtmlModel.endsWith(Const.LOGIN_TYPE_HTML[1])){                     type = 1;//后台账号未登录                }            //    int type = (SessionUtil.getAttribute(Const.LOGIN_TYPE)!=null)?Integer.valueOf(SessionUtil.getAttribute(Const.LOGIN_TYPE).toString()):0;            if(regAccout==null){//平台账号未登录                if(tarUri.endsWith(".do")){                    httpResp.sendRedirect(ctxPath+"/"+Const.TIMEOUT_SERVICE);                    return;                                                }else if(tarUri.endsWith("/")){                    httpResp.sendRedirect(ctxPath+"/"+Const.INDEX_PAGE);                    return;                }            }else{//平台账号登录                if(tarUri.endsWith("/")){                    httpResp.sendRedirect(ctxPath+"/error/noSecurity.htm");                    return;                }else if(tarUri.endsWith(".do") && !isWithoutUri(tarUri)){                    String contentType = httpReq.getContentType();//获取请求的content-type                    String post_csrftoken = "";                    if(contentType.contains("multipart/form-data")){//文件上传请求 *特殊请求
              /*
                
CommonsMultipartResolver 是spring框架中自带的类,使用multipartResolver.resolveMultipart(final HttpServletRequest request)方法可以将request转化为MultipartHttpServletRequest
                使用MultipartHttpServletRequest对象可以使用getParameter(key)获取对应属性的值
              */
                        MultipartHttpServletRequest multiReq = multipartResolver.resolveMultipart(httpReq);                        post_csrftoken=multiReq.getParameter(Const.SESSION_CSRFTOKEN);//获取参数中的token                        req = multiReq;//将转化后的reuqest赋值到过滤链中的参数 *重要                    }else{//非文件上传请求                        post_csrftoken=httpReq.getParameter(Const.SESSION_CSRFTOKEN);//获取参数中的token                    }                    //csrf防御:判断是否带token                    //post_csrftoken=httpReq.getParameter(Const.SESSION_CSRFTOKEN);                    String csrftoken=(String)SessionUtil.getAttribute(Const.SESSION_CSRFTOKEN);                    if(post_csrftoken==null || !csrftoken.equals(post_csrftoken)){                        //判断为不安全的访问                        httpResp.sendRedirect(ctxPath+"/common/goNoSecurity.do");                        return;                    }                }            }            // 设定网页的到期时间,一旦过期则必须到服务器上重新调用            httpResp.setDateHeader("Expires", -1);            // Cache-Control 指定请求和响应应遵循的缓存机制 no-cache指示请求或响应消息是不能缓存的            httpResp.setHeader("Cache-Control", "no-cache");            // 用于设定禁止浏览器从本地缓存中调用页面内容,设定后一旦离开页面就无法从Cache中再调出            httpResp.setHeader("Pragma", "no-cache");            }                chain.doFilter(req, resp);        }    }        @SuppressWarnings("unchecked")    @Override    public void init(FilterConfig cfg) throws ServletException {        //初始化操作    }        private Boolean isWithoutUri(String tarUri){        String[] withoutUriStrings = {//无需匹配token的请求                "/common/goNoSecurity.do",                "/plateFormCommon/isLoginForPlateForm.do",                "/supplierForPlateForm/getCompanyListByRegId.do"                /*,"/PfTaskFileCtrl/addOrUpdateTaskImgFile1.do"*/                /*,"/PfTaskFileCtrl/addOrUpdateTaskImgFileForUpdate.do"*/                };                for(String uri:withoutUriStrings){            if(uri.equals(tarUri)){                return true;            }        }        return false;    }    }
复制代码

 

 

  3.3 控制层 PfTaskFileCtrl.java

  如果在filter中未将转化的request值赋值给过滤链,则在这里无法获取fileType对应的值;

复制代码
package platform.common.controller;/**     * mogodb文件上传下载 * 项目名称:outsideeasy     * 类名称:PfTaskFileCtrl     * 创建人:mishengliang     * 创建时间:2016-4-26 下午1:55:19     * 修改人:mishengliang     * 修改时间:2016-4-26 下午1:55:19     * @version      *      */@Controller@RequestMapping("PfTaskFileCtrl")public class PfTaskFileCtrl {    @Autowired    private PfRegisterAttchedService registerAttchedService;    @Autowired    private FileOptService fileService;    @Autowired    private PfUpdateRegisterAttchedService updateRegisterAttchedService;    @Autowired    private CompanyForPlateFormService companyForPlateFormService;        @RequestMapping(value = { "/companyImageView" }, method = { RequestMethod.GET })    public ModelAndView gojsp_companyImageView(ModelAndView modelAndView ){        modelAndView.setViewName("/companyWindow/companyImageView");        return modelAndView;    }        /**     * @Description:企业文件上传     * PfTaskFileCtrl     * addOrUpdateTaskImgFile1     * @param request     * @param response     * @return     * @throws Exception String     * @author yukai     * 2016-8-4 上午10:03:00     */    @DocLogger(explain="企业文件上传")    @RequestMapping(value="addOrUpdateTaskImgFile1",method=RequestMethod.POST)    @ResponseBody     public String addOrUpdateTaskImgFile1(HttpServletRequest request,HttpServletResponse response) throws Exception{        Map<String,Object> qryParam = WebUtil.getDefaultParamsMap(request);        LoginAccount regAccount = SessionUtil.getCurrentPlateLoginAccount();        Map<String,Object> params=new HashMap<String, Object>();        JSONObject json = new JSONObject();        json.put("success", true);        /*         * 1.检查参数         */        if(regAccount == null){//获取任务id            json.put("message", "未登录");            return json.toString() ;        }
     // *如果在filter中未将转化的request值赋值给过滤链,则在这里无法获取fileType对应的值
if(WebUtil.isEmpty(request.getParameter("fileType"))){//获取任务id json.put("message", "没有文件类型值"); return json.toString() ; } /* *2.赋值 */ int fileType = Integer.parseInt(request.getParameter("fileType")); String fileName = request.getParameter("fileName"); String formatType = request.getParameter("formatType"); PfRegisterAttched pfRegisterAttched = new PfRegisterAttched(); pfRegisterAttched.setFile_type_id(fileType);//文件类型值 pfRegisterAttched.setFile_name(fileName);//文件名 if(fileName.indexOf(",") != -1){ json.put("message", "文件名中存在非法字符(英文逗号),请先去除后上传"); return json.toString() ; } /* * 3.对文件信息的处理 */ MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; if(WebUtil.isEmpty((CommonsMultipartFile) multipartRequest.getFile("file"))){ json.put("message", "没有文件"); return json.toString() ; } CommonsMultipartFile file = (CommonsMultipartFile) multipartRequest.getFile("file"); //对应前台文件对象 if(file!=null && file.getSize()>0){//检查文件大小和格式 if (file.getSize() >5*1024*1024) { json.put("message", "文件太大,超过5M"); return json.toString() ; } String originalName=file.getOriginalFilename(); String this_suffix = ""; params.put(Const.ISIMG, 0); params.put(Const.USE_TYPE, fileType); params.put(Const.USERNAME, regAccount.getLogin_name()); params.put(Const.COM_ID, qryParam.get("companyId")); params.put(Const.COM_NAME,companyForPlateFormService.getCompanyNameByCompanyId(qryParam)); boolean flag=false;//默认不 是图片 //获取文件后缀,与传过来的参数file_name重新组装文件名 if(originalName.indexOf(".")>0){//有后缀 XX.jpg XX.RAR this_suffix=originalName.substring(originalName.lastIndexOf(".")); String[] format = null; if("image".equals(formatType)){//判断上传文件的类型:image 图片,text 文档 format = Const.imgArray; params.put(Const.ISIMG, 1); }else if("text".equals(formatType)){ format = Const.otherArray; } for(String suffix:format){ if(suffix.equalsIgnoreCase(this_suffix)){ flag=true; break; } } } if(!flag){ json.put("message", "不是指定格式"); return json.toString() ; }else{ /* * 4.进行信息的处理 */ Date date = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String mongodbId=fileService.SaveFile(file,params); pfRegisterAttched.setMogodb_id(mongodbId);//把存储mongoDb的文件序号存到数据库中 pfRegisterAttched.setCreate_dt(date); pfRegisterAttched.setFile_format(this_suffix); Integer id = registerAttchedService.addAppRegisterAttched(pfRegisterAttched);//获取存入信息的id json.put("fileId",id); json.put("mongodbId", mongodbId); json.put("creatDate", sf.format(date)); json.put("message", "上传成功"); } }else{ json.put("message", "文件不存在"); } return json.toString(); } }
复制代码

 

 

4.解决方案

  在问题描述中已有问题解决方案。

  此方法主要利用了Spring框架中已有的工具类。

  参考资料:http://www.itdadao.com/articles/c15a279110p0.html

 

 

5.总结

  5.1 不同的content-type请求获取参数值的方法不同。

  5.2 在multipart/form-data请求方式中,需要利用SpringMVC框架中的CommonsMultipartResolver类包装转化为MultipartHttpServletRequest获取参数值;

 

 

6. 参考学习

  1. servlet3.0 Tomcat7.0 简洁方案

    如果使用的是servlet3.0及以上版本,multipart/form-data请求方式取值可以使用 HttpServletRequest.getPart(key)方法获取指定值;

    参考资料:http://stackoverflow.com/questions/2422468/how-to-upload-files-to-server-using-jsp-servlet/2424824#2424824

 

 

 

  2.通常的三种请求方式获取值方法

    * application/x-www-form-urlencoded

    *application/json

    * text/xml 

 

  可以使用将请求转化为流,再转为字符串获取相应的值,通过如下方法获取的字符串获取指定的参数值;

  转化方法如下:

复制代码
    /**      * 获取请求Body      *      * @param request      * @return      */      public static String getBodyString(ServletRequest request) {          StringBuilder sb = new StringBuilder();          InputStream inputStream = null;          BufferedReader reader = null;          try {              inputStream = request.getInputStream();              reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));              String line = "";              while ((line = reader.readLine()) != null) {                  sb.append(line);              }          } catch (IOException e) {              e.printStackTrace();          } finally {              if (inputStream != null) {                  try {                      inputStream.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }              if (reader != null) {                  try {                      reader.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }          }          return sb.toString();      }  
复制代码

 

  参考资料:http://blog.csdn.net/pyxly1314/article/details/51802652

    


0 0