struts2 request.getInpustream()及multipart上传获取不到数据的解决方案

此问题是之前在项目中遇到并解决的,今天将其记录一下。项目中遇到的需求是,要在拦截器中将请求post过来的数据流进行解析,然后手动将解析的各参数其压到struts2的valueStack中,post过来的数据流可能是json串形式(客户端没有标记content-type)或者以multipart/form-data形式发送过来的语音文件(二进制)和json串两种情况。我的实现思路是,判断如果request是multipart的话就是使用commons-file分解出语音数据和json串,否则,就直接使用getInputStream获取出json串。

但是,当传过来的数据是multipart/form-data形式时,发现从request中解析的文件(FileItem)列表为空

获取multipart请求部分代码如下:

[java] view plain copy
  1. FileItemFactory factory = new DiskFileItemFactory();  
  2. ServletFileUpload upload = new ServletFileUpload(factory);  
  3. List<FileItem> items = null;  
  4. items = upload.parseRequest(request);  

在确定了发送过来的数据没有错误之后,就去网上查找资料,原来,这里的request是被struts2 进行封装的,已经不再是原生的Servlet 请求,所以这个request无法被ServletFileUpload 解析,这就导致了列表为空,解决的方法就是,使用没有被struts2封装过的request,可以在struts.xml中指定文件上传使用的request解析器,如下:

[html] view plain copy
  1. <!-- 使struts2不对request上传请求进行封装 -->  
  2.     <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"  
  3.         name="myRequestParser" class="com.dear.vpInterface.utils.RequestParseWrapper"  
  4.         scope="default" optional="true" />  
  5.     <constant name="struts.multipart.parser" value="myRequestParser" />  
其中com.dear.vpInterface.utils.RequestParseWrapper是自己实现的类:
[java] view plain copy
  1. package com.dear.vpInterface.utils;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.http.HttpServletRequest;  
  6.   
  7. import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;  
  8.   
  9. public class RequestParseWrapper extends JakartaMultiPartRequest {  
  10.     // 这里对parse方法进行了覆盖,使其无法封装request  
  11.     @Override  
  12.     public void parse(HttpServletRequest request, String saveDir)  
  13.             throws IOException {  
  14.   
  15.     }  
  16.   
  17. }  
这样的话,上述的数据就解决了。


但是,在获取json串的时候,发现使用request.getInputStream()获取的数据竟然也为null。(/(ㄒoㄒ)/~~ ,真是祸不单行,为啥要用struts2),原来在struts2中要去传递过来的报文的content-type进行设置(比如客户端发送json,content-type应为application/json),否则会被struts2拦截,放到request的ParameterMap中,但是由于我只是做服务端的,客户端发送的数据带不带content-type不受我控制,不管客户端带不带content-type,我这边必须都要兼容(/(ㄒoㄒ)/~~),由于传送的请求报文体的不是类似Key=value的形式,而是json,所以这个json应该被放到了ParameterMap的第一个key里面,于是我使用Set<String> set = request.getParameterMap().keySet(),使用遍历这个key的第一个元素,就是json串,事实证明这是正确的。于是问题解决。


以下是具体的自定义的拦截器代码:

[java] view plain copy
  1. package com.dear.vpInterface.interceptor;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.util.Iterator;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9. import java.util.Set;  
  10.   
  11. import javax.servlet.http.HttpServletRequest;  
  12.   
  13. import org.apache.commons.fileupload.FileItem;  
  14. import org.apache.commons.fileupload.FileItemFactory;  
  15. import org.apache.commons.fileupload.FileUploadException;  
  16. import org.apache.commons.fileupload.disk.DiskFileItemFactory;  
  17. import org.apache.commons.fileupload.servlet.ServletFileUpload;  
  18. import org.apache.struts2.StrutsStatics;  
  19.   
  20. import com.dear.vpInterface.helper.InterException;  
  21. import com.dear.vpInterface.utils.JsonUtil;  
  22. import com.dear.vpInterface.utils.NameUtil;  
  23. import com.dear.vpInterface.utils.PropertyUtil;  
  24. import com.dear.vpInterface.utils.HttpError;  
  25. import com.dear.vpInterface.utils.StreamUtil;  
  26. import com.opensymphony.xwork2.ActionContext;  
  27. import com.opensymphony.xwork2.ActionInvocation;  
  28. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;  
  29. import com.opensymphony.xwork2.util.ValueStack;  
  30.   
  31.   
  32. public class MessageFormatInterceptor extends AbstractInterceptor{  
  33.       
  34.       
  35.     private static final long serialVersionUID = 1L;  
  36.     private static final String INTER_EXCEPTION = "interException";  
  37.       
  38.       
  39.     @Override  
  40.     public String intercept(ActionInvocation invocation) throws Exception{   
  41.         ActionContext ctx = invocation.getInvocationContext();  
  42.         HttpServletRequest request= (HttpServletRequest) ctx.get(StrutsStatics.HTTP_REQUEST);    
  43.         ValueStack stack = ctx.getValueStack();  
  44.           
  45.         Map<String,Object> reqMap = null;  
  46.         try{  
  47.             reqMap = getMapFromRequestJson(request);      
  48.         }catch(InterException e){  
  49.             request.setAttribute("exception", e);  
  50.             return INTER_EXCEPTION;  
  51.         }  
  52.         setParam2Stack(reqMap, stack);  
  53.         }  
  54.           
  55.         return invocation.invoke();  
  56.     }  
  57.       
  58.       
  59.       
  60.       
  61.       
  62.       
  63.     //从请求中得到参数Map  
  64.     public Map<String,Object> getMapFromRequestJson(HttpServletRequest request) throws InterException{  
  65.         String reqJson = null;  
  66.         byte[] voiceByte = null;  
  67.         boolean isVoiceByteExisted = false;  
  68.         boolean isMultipart = ServletFileUpload.isMultipartContent(request);  
  69.         try {  
  70.             if (isMultipart == true) {  
  71.                  FileItemFactory factory = new DiskFileItemFactory();  
  72.                  ServletFileUpload upload = new ServletFileUpload(factory);  
  73.                  List<FileItem> items = null;  
  74.                  items = upload.parseRequest(request);  
  75.                  Iterator<FileItem> iterator = items.iterator();  
  76.                  while (iterator.hasNext()) {  
  77.                      FileItem item = iterator.next();  
  78.                      if (item.isFormField()) {  
  79.                          InputStream inputStream = item.getInputStream();  
  80.                          reqJson = StreamUtil.stream2String(inputStream);   
  81.                      } else {  
  82.                          voiceByte = getFile(item);  
  83.                          isVoiceByteExisted = true;  
  84.                      }  
  85.                  }  
  86.             }else{  
  87.                     reqJson = StreamUtil.stream2String(request.getInputStream());  //客户端指定了Content-Type  
  88.                 if(reqJson == null || "".equals(reqJson)){             //客户端没有指定Content-Type  
  89.                     Set<String> set = request.getParameterMap().keySet();  
  90.                     Iterator<String> it = set.iterator();  
  91.                     if(it.hasNext()){  
  92.                         reqJson = it.next();  
  93.                     }  
  94.                 }  
  95.             }  
  96.         } catch (IOException e) {  
  97.             throw new InterException(HttpError.SMB_HTTP_INPUT_JSON_ERROR);  
  98.         } catch (FileUploadException e) {  
  99.             throw new InterException(HttpError.SMB_HTTP_INPUT_JSON_ERROR);  
  100.         }  
  101.         Map<String,Object> reqMap = JsonUtil.getMap4Json(reqJson);  
  102.         if(isVoiceByteExisted){  
  103.             reqMap.put("voiceByte", voiceByte);  
  104.         }  
  105.         return reqMap;  
  106.     }  
  107.       
  108.     //将请求参数压入值栈  
  109.     public void setParam2Stack(Map<String,Object> reqMap,ValueStack stack){  
  110.         boolean isVpIdContained = false;  
  111.         String value = null;  
  112.         for(String key : reqMap.keySet()){  
  113.             //将json的下划线命名转换为java的驼峰  
  114.             stack.setValue(NameUtil.underlineToCamel(key), reqMap.get(key));  
  115.         }  
  116.     }  
  117.       
  118.     protected static byte[] getFile(FileItem item) throws IOException {  
  119.         InputStream in = item.getInputStream() ;  
  120.         ByteArrayOutputStream outStream = new ByteArrayOutputStream() ;    
  121.         byte[] data = new byte[64*1024] ;    
  122.         int count = -1 ;  
  123.         while((count = in.read(data,0,1024)) != -1){    
  124.             outStream.write(data, 0, count) ;    
  125.         }  
  126.         byte[] fileByte = outStream.toByteArray();  
  127.         in.close();  
  128.         outStream.close();  
  129.         return fileByte;  
  130.     }  

猜你喜欢

转载自blog.csdn.net/dhq_blog/article/details/80610427
今日推荐