struts2 request.getInpustream()およびmultipartアップロードでデータが取得できないソリューション

6707 ワード

この問題は、以前にプロジェクトで発生し、解決されたもので、今日記録します.プロジェクトで遭遇する要件は,ブロックでpostを要求してきたデータストリームを解析し,解析した各パラメータをstruts 2のvalueStackに手動で押し付けることである.postからのデータストリームは、json列形式(クライアントがcontent-typeをマークしていない)またはmultipart/form-data形式で送信された音声ファイルである可能性があります.(バイナリ)とjson列の2つの場合.私の実現構想は、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はstruts 2によってカプセル化されており、もはやオリジナルのサーブレットリクエストではないので、このrequestはサーブレットFileUploadによって解析できないため、リストが空になり、解決策はstruts 2にカプセル化されていない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ㄒ)/~~~本当に災いが重なって、なぜstruts 2を使うのか)、struts 2で渡されるメッセージのcontent-typeを設定しなければならない(例えばクライアントがjsonを送信し、content-typeがapplication/jsonであるべきである)、そうしないとstruts 2にブロックされ、requestのParameterMapに置かれるが、私はサービス側であるだけなので、クライアントが送信データバンドはcontent-typeを持たない私の制御を受けないで、クライアントバンドがcontent-typeを持たないに関わらず、私の側はすべて互換性がある必要があります(/(ㄒoㄒ)/~~~~~))、伝送する要求メッセージの体はKey=valueのような形式ではなく、jsonなので、このjsonはParameterMapの最初のkeyの中に置かれるべきで、そこで私は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;
	}
}