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请求部分代码如下:

FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = null;
items = upload.parseRequest(request);

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


	
	
其中com.dear.vpInterface.utils.RequestParseWrapper是自己实现的类:
package com.dear.vpInterface.utils;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;

public class RequestParseWrapper extends JakartaMultiPartRequest {
	// 这里对parse方法进行了覆盖,使其无法封装request
	@Override
	public void parse(HttpServletRequest request, String saveDir)
			throws IOException {

	}

}
这样的话,上述的数据就解决了。


但是,在获取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 set = request.getParameterMap().keySet(),使用遍历这个key的第一个元素,就是json串,事实证明这是正确的。于是问题解决。


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

package com.dear.vpInterface.interceptor;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.struts2.StrutsStatics;

import com.dear.vpInterface.helper.InterException;
import com.dear.vpInterface.utils.JsonUtil;
import com.dear.vpInterface.utils.NameUtil;
import com.dear.vpInterface.utils.PropertyUtil;
import com.dear.vpInterface.utils.HttpError;
import com.dear.vpInterface.utils.StreamUtil;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.ValueStack;


public class MessageFormatInterceptor extends AbstractInterceptor{
	
	
	private static final long serialVersionUID = 1L;
	private static final String INTER_EXCEPTION = "interException";
	
	
	@Override
	public String intercept(ActionInvocation invocation) throws Exception{ 
	    ActionContext ctx = invocation.getInvocationContext();
	    HttpServletRequest request= (HttpServletRequest) ctx.get(StrutsStatics.HTTP_REQUEST);  
	    ValueStack stack = ctx.getValueStack();
		
		Map reqMap = null;
		try{
			reqMap = getMapFromRequestJson(request);	
		}catch(InterException e){
			request.setAttribute("exception", e);
			return INTER_EXCEPTION;
		}
		setParam2Stack(reqMap, stack);
		}
		
		return invocation.invoke();
	}
	
	
	
	
	
	
	//从请求中得到参数Map
	public Map getMapFromRequestJson(HttpServletRequest request) throws InterException{
		String reqJson = null;
		byte[] voiceByte = null;
		boolean isVoiceByteExisted = false;
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		try {
			if (isMultipart == true) {
				 FileItemFactory factory = new DiskFileItemFactory();
				 ServletFileUpload upload = new ServletFileUpload(factory);
				 List items = null;
				 items = upload.parseRequest(request);
				 Iterator iterator = items.iterator();
				 while (iterator.hasNext()) {
					 FileItem item = iterator.next();
					 if (item.isFormField()) {
					     InputStream inputStream = item.getInputStream();
					     reqJson = StreamUtil.stream2String(inputStream); 
				     } else {
				    	 voiceByte = getFile(item);
				    	 isVoiceByteExisted = true;
				     }
				 }
		    }else{
					reqJson = StreamUtil.stream2String(request.getInputStream());  //客户端指定了Content-Type
				if(reqJson == null || "".equals(reqJson)){             //客户端没有指定Content-Type
					Set set = request.getParameterMap().keySet();
					Iterator it = set.iterator();
					if(it.hasNext()){
						reqJson = it.next();
					}
				}
		    }
		} catch (IOException e) {
			throw new InterException(HttpError.SMB_HTTP_INPUT_JSON_ERROR);
		} catch (FileUploadException e) {
			throw new InterException(HttpError.SMB_HTTP_INPUT_JSON_ERROR);
		}
		Map reqMap = JsonUtil.getMap4Json(reqJson);
		if(isVoiceByteExisted){
			reqMap.put("voiceByte", voiceByte);
		}
		return reqMap;
	}
	
	//将请求参数压入值栈
	public void setParam2Stack(Map reqMap,ValueStack stack){
		boolean isVpIdContained = false;
		String value = null;
		for(String key : reqMap.keySet()){
			//将json的下划线命名转换为java的驼峰
			stack.setValue(NameUtil.underlineToCamel(key), reqMap.get(key));
		}
	}
	
	protected static byte[] getFile(FileItem item) throws IOException {
		InputStream in = item.getInputStream() ;
		ByteArrayOutputStream outStream = new ByteArrayOutputStream() ;  
        byte[] data = new byte[64*1024] ;  
        int count = -1 ;
        while((count = in.read(data,0,1024)) != -1){  
            outStream.write(data, 0, count) ;  
        }
        byte[] fileByte = outStream.toByteArray();
        in.close();
        outStream.close();
        return fileByte;
	}
}



你可能感兴趣的:(java,问题记录)