但是,当传过来的数据是multipart/form-data形式时,发现从request中解析的文件(FileItem)列表为空
获取multipart请求部分代码如下:
- FileItemFactory factory = new DiskFileItemFactory();
- ServletFileUpload upload = new ServletFileUpload(factory);
- List<FileItem> items = null;
- items = upload.parseRequest(request);
在确定了发送过来的数据没有错误之后,就去网上查找资料,原来,这里的request是被struts2 进行封装的,已经不再是原生的Servlet 请求,所以这个request无法被ServletFileUpload 解析,这就导致了列表为空,解决的方法就是,使用没有被struts2封装过的request,可以在struts.xml中指定文件上传使用的request解析器,如下:
- <!-- 使struts2不对request上传请求进行封装 -->
- <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
- name="myRequestParser" class="com.dear.vpInterface.utils.RequestParseWrapper"
- scope="default" optional="true" />
- <constant name="struts.multipart.parser" value="myRequestParser" />
- 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<String> 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<String,Object> 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<String,Object> 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<FileItem> items = null;
- items = upload.parseRequest(request);
- Iterator<FileItem> 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<String> set = request.getParameterMap().keySet();
- Iterator<String> 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<String,Object> reqMap = JsonUtil.getMap4Json(reqJson);
- if(isVoiceByteExisted){
- reqMap.put("voiceByte", voiceByte);
- }
- return reqMap;
- }
- //将请求参数压入值栈
- public void setParam2Stack(Map<String,Object> 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;
- }
- }