spring mvc post方法接收参数为null

问题描述:今天在项目中遇到一个问题,一个报表插件,导出excel数据文件格式,实现原理是将需要下载的数据,按照excel格式(xml数据)内容生成好以后发送之后服务端,然后在服务端生成excel文件,再通过流的形式返回给客户端,完成excel数据下载功能。


在实际运行中,发现在下载文件时,数据内容量小,也就是生成的excel数据内容较少的时候,文件下载正常。但在数据量较大时(我们实际保存文件有3.6M),客户端调用action的方法时,调试发现参数都为null,方法定义如下:

Controller 方法映射如下:
    /××
     ×@param fileName 文件名称
     ×@param format   文件格式,可以支持excel,csv,html,pdf
     ×@param content  文件内容,按照需要下载的文件格式,将文件格式与数据一起生成好
     ××/
    @RequestMapping(params = "file=true", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<byte[]> export(String fileName,String format,String content) {
          省略写文件细节,主要看方法定义
     }

为了测试是什么问题导致的参数都为null,我就自己写了个servlet,servlet实现了doPost方法,读取了post请求的消息体,然后将客户端的下载文件请求发送至servlet上,跟上述大文件下载时一样的数据请求,发现参数其实可以可以接收到的,但使用spring mvc调用方法后参数就都为null了,所以可以判断问题处在spring mvn参数解析上。但因为今天项目bug修改任务比较急,在网上搜索一番后,并没有针对这个问题的解决方案,所以我果断采取在action 方法里自己实现读取body,并解析parameter,具体修改如下:
    @RequestMapping(params = "file=true", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<byte[]> export(HttpServletRequest request) {
  String body = readyBody(request);
        Map<String,String> paramMap = parsePostBodyParam(body);
        String filename = null,format=null,content=null;
        if(paramMap!=null&&!paramMap.isEmpty()){
            filename = paramMap.get("filename");
            format = paramMap.get("format");
            content = paramMap.get("content");
        }
}
private  String readyBody(HttpServletRequest req) {
        StringBuilder body = new StringBuilder();
        BufferedReader br =null;
        String line = null;
        try {
            InputStreamReader reader = new InputStreamReader(req.getInputStream());
            br = new BufferedReader(reader);
            while ((line=br.readLine())!=null){
                body.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (br!=null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return body.toString();
    }
   private Map<String,String> parsePostBodyParam(String body){
        Map<String,String> paramMap = new HashMap<String,String>();
        if(StringUtils.isNotBlank(body)){
            String[] params = body.split("&");
            if(params!=null&¶ms.length>0){
                String[] nameValue = null;
                for(String param : params){
                        nameValue = param.split("=");
                        if(nameValue!=null&&nameValue.length==2){
                            try {
                                paramMap.put(nameValue[0], URLDecoder.decode(nameValue[1],"UTF-8"));
                                System.out.println("post body param key : "+nameValue[0]+" value : "+nameValue[1]);
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                }
            }
        }
        return paramMap;
    }






  
  
在方法参数中直接使用了HttpServletRequest,然后自己读取body中的信息,确认客户端是以content-type 为application/x-www-form-urlencoded方式发送请求,所以自己按照fileName=value&format=value&content=value方式将参数解析称map,然后与之前开发写文件代码结合完成文件下载功能,至此bug修复。

待续:自己后续会研读spring源码,希望可以发现问题的根本原因,并通过解决参数解析实现来解决问题。


方案改进:此文件下载方案性能问题较多,1.数据量大时,客户端浏览器会直接崩溃。2.客户端将数据+文件格式大量数据发送至服务端,服务端再将生成好的文件返回给客户端,这样会增加服务端网络压力。希望结合前段分页数据导出组件,实现将文件生成由服务器段控制,然后将生成好的文件返回给客户端。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值