如何初始化自定义HttpServeletRequest的Multipart请求

时间:2017-10-04 07:06:56

标签: java file-upload multipart

我正在使用springboot 2x。我们的项目使用Custom HttpServeletRequest,它扩展了HttpServletRequestWrapper并实现了MultipartHttpServletRequest。一切正常。但是当我想为文件上传工作时,它无法初始化Multipart请求。它显示错误:

java.lang.IllegalStateException: Multipart request not initialized

我的问题是,如何解决此错误。如何初始化Multipart请求。

我正在提供有关此事的所有代码。

public class XHttpServletRequest extends HttpServletRequestWrapper implements MultipartHttpServletRequest {

  public XHttpServletRequest (HttpServletRequest request) {
    super(request);
  }

  private MultiValueMap<String, MultipartFile> multipartFiles;

  private String method;

  @Override
  public String getMethod() {
    if (this.method == null) return super.getMethod();
    return this.method;
  }

  public void setMethod(String method) {
    this.method = method;
  }

  private Map<String,String[]> parameters = new LinkedHashMap<String,String[]>();


  public void setParameter(String name, String value) {
    parameters.put(name, new String[] {value});
  }

  @Override
  public String getParameter(String name) {
    if (parameters.get(name) != null) {
      return parameters.get(name)[0];
    }
    HttpServletRequest req = (HttpServletRequest) super.getRequest();
    return req.getParameter(name);
  }

  public Map<String, String[]> getParameterMap() {
    Map<String, String[]> result = new LinkedHashMap<String, String[]>();
    result.putAll(super.getRequest().getParameterMap());
    result.putAll(parameters);
    return Collections.<String, String[]>unmodifiableMap(result);
  }

  public Enumeration<String> getParameterNames() {
    Set<String> result = new LinkedHashSet<String>(Collections.list(super.getRequest().getAttributeNames()));
    result.addAll(parameters.keySet());
    return new Vector<String>(result).elements();
  }

  public String[] getParameterValues(String name) {
    if (parameters.get(name) != null) {
      return parameters.get(name);
    }
    HttpServletRequest req = (HttpServletRequest) super.getRequest();
    return req.getParameterValues(name);
  }


    @Override
    public HttpServletRequest getRequest() {
        return (HttpServletRequest) super.getRequest();
    }

    @Override
    public HttpMethod getRequestMethod() {
        return HttpMethod.resolve(getRequest().getMethod());
    }

    @Override
    public HttpHeaders getRequestHeaders() {
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.put(headerName, Collections.list(getHeaders(headerName)));
        }
        return headers;
    }

  @Override
  public HttpHeaders getMultipartHeaders(String s) {
    return null;
  }

  @Override
    public Iterator<String> getFileNames() {
        return getMultipartFiles().keySet().iterator();
    }

    @Override
    public MultipartFile getFile(String name) {
        return getMultipartFiles().getFirst(name);
    }

    @Override
    public List<MultipartFile> getFiles(String name) {
        List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
        if (multipartFiles != null) {
            return multipartFiles;
        }
        else {
            return Collections.emptyList();
        }
    }

    @Override
    public Map<String, MultipartFile> getFileMap() {
        return getMultipartFiles().toSingleValueMap();
    }

    @Override
    public MultiValueMap<String, MultipartFile> getMultiFileMap() {
        return getMultipartFiles();
    }

  @Override
  public String getMultipartContentType(String s) {
    return null;
  }


  /**
     * Set a Map with parameter names as keys and list of MultipartFile objects as values.
     * To be invoked by subclasses on initialization.
     */
    protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
        this.multipartFiles =
                new LinkedMultiValueMap<>(Collections.unmodifiableMap(multipartFiles));
    }

    /**
     * Obtain the MultipartFile Map for retrieval,
     * lazily initializing it if necessary.
     * @see #initializeMultipart()
     */
    protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
        if (this.multipartFiles == null) {
            initializeMultipart();
        }
        return this.multipartFiles;
    }

    /**
     * Lazily initialize the multipart request, if possible.
     * Only called if not already eagerly initialized.
     */
    protected void initializeMultipart() {
        throw new IllegalStateException("Multipart request not initialized");
    }
}

另一个类扩展了XHttpServletRequest,而不是我们项目中的HttpServeletRequest。以下代码:

public class YHttpRequest extends MutableHttpServletRequest {
  private ByteArrayOutputStream cachedBytes;

  public YHttpRequest(HttpServletRequest request) {
    super(request);
  }

  @Override
  public ServletInputStream getInputStream() throws IOException {
    if (cachedBytes == null)
      cacheInputStream();

    return new CachedServletInputStream();
  }

  @Override
  public BufferedReader getReader() throws IOException{
    return new BufferedReader(new InputStreamReader(getInputStream()));
  }

  private void cacheInputStream() throws IOException {
  /* Cache the inputstream in order to read it multiple times. For
   * convenience, I use apache.commons IOUtils
   */
    cachedBytes = new ByteArrayOutputStream();
    IOUtils.copy(super.getInputStream(), cachedBytes);
  }

  public List<Map<String, Object>> getListData() throws RequestException {

    List<Map<String, Object>> data = new ArrayList<>();

    try {

      ObjectMapper mapper = new ObjectMapper();

      data = mapper.readValue(this.getInputStream(), new TypeReference<ArrayList<LinkedHashMap>>(){});

      System.out.println(data);
    }
    catch (Exception e) {
//      System.out.println(e.)
      throw new RequestException("Unable to parse request data", e);
    }

    return data;
  }

  private Object cachedData = null;

  public Object getRawData() throws RequestException {

    Object data = new LinkedHashMap<>();

    try {

      ObjectMapper mapper = new ObjectMapper();

//      data = mapper.readValue(this.getInputStream());
      try {
        data = mapper.readValue(this.getInputStream(), new TypeReference<HashMap>() {
        });
      }
      catch (JsonMappingException e) {
//        e.printStackTrace();
      }

      try {
        data = mapper.readValue(this.getInputStream(), new TypeReference<List<HashMap>>() {
        });
      }
      catch (JsonMappingException e) {
//        e.printStackTrace();
      }
      System.out.println(data);
    }
    catch (Exception e) {
//      System.out.println(e.)
      throw new RequestException("Unable to parse request data", e);
    }

    return data;
  }

  public Object getData() throws RequestException {
    if (this.cachedData == null) {
      this.cachedData = this.getRawData();
    }

    return this.cachedData;
  }


  /* An inputstream which reads the cached request body */
  public class CachedServletInputStream extends ServletInputStream {
    private ByteArrayInputStream input;

    public CachedServletInputStream() {
    /* create a new input stream from the cached request body */
      input = new ByteArrayInputStream(cachedBytes.toByteArray());
    }

    @Override
    public boolean isFinished() {
      return input.available() == 0;
    }

    @Override
    public boolean isReady() {
      return true;
    }

    @Override
    public void setReadListener(ReadListener readListener) {
//      throw new IOException("zubair says: Method not implemented in Cached Servlet Input Stream class");
    }

    @Override
    public int read() throws IOException {
      return input.read();
    }
  }

  // Storage for Path variable
  private Map<String, Object> pathVariableMap = null;

  public Map<String, Object> getPathVariableMap() {
    if (this.pathVariableMap == null) {
      this.pathVariableMap = new LinkedHashMap<>();
      this.pathVariableMap.putAll((Map<? extends String, ?>) this.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE));
    }
    return this.pathVariableMap;
  }

  public Object getPathVariable(String key) {
    return this.getPathVariableMap().get(key);
  }

  public FurinaHttpRequest setPathVariable(String key, Object value) {
    this.getPathVariableMap().put(key, value);
    return this;
  }

  public FurinaHttpRequest clearPathVariableMap() {
    this.getPathVariableMap().clear();
    return this;
  }


}

控制器代码:

public String handleFileUpload(YHttpRequest request) {

        if (request.getMethod().equalsIgnoreCase("GET")){
            return "{}";
        }

        Map<String, MultipartFile> file= request.getFileMap();
        try {
            for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
                storageService.store(entry.getValue());
                //model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
                files.add(entry.getValue().getOriginalFilename());
            }

        } catch (Exception e) {
            //model.addAttribute("message", "FAIL to upload !");
        }
        return "{}";
    }

1 个答案:

答案 0 :(得分:0)

这将有效

public String handleFileUpload(YHttpRequest request) {

            if (request.getMethod().equalsIgnoreCase("GET")){
                return "{}";
            }
    StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = new StandardMultipartHttpServletRequest(request);

            Map<String, MultipartFile> file= request.getFileMap();
            try {
                for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
                    storageService.store(entry.getValue());
                    //model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
                    files.add(entry.getValue().getOriginalFilename());
                }

            } catch (Exception e) {
                //model.addAttribute("message", "FAIL to upload !");
            }
            return "{}";
        }