복붙노트

[SPRING] Spring 3.0 FileUpload는 POST에서만 사용할 수 있습니까?

SPRING

Spring 3.0 FileUpload는 POST에서만 사용할 수 있습니까?

Spring 3을 사용하여 하나의 매개 변수로 File을 업로드하려고합니다.

이것은이 서비스를 활성화해야하는 컨트롤러 방법입니다.

@RequestMapping(value="/{id}", method = RequestMethod.PUT, headers="content-type=multipart/form-data")
public ResponseEntity<String> uploadImageWithJsonParamater(@PathVariable("id") Long id, @RequestParam String json, @RequestParam MultipartFile customerSignFile) {
    //...
}

문제는 서버가이 메소드로 디스패치 할 수 없다는 것입니다. MissingServletRequestParameterException : 필수 문자열 매개 변수 'json'이 (가) 없습니다.

RequestMethod를 PUT에서 POST로 변경하면 모든 것이 정상입니다. 그렇다면 누구도 문제를 알고 있습니까?

PUT을 통해 양식 데이터를 전송하는 것은 허용되지 않는 것으로 보입니다.

약간의 디버깅을했고 다음 메소드는 PUT의 경우에는 false를 반환하지만 POST의 경우에는 true를 반환합니다.

public boolean isMultipart(HttpServletRequest request) {
    return (request != null && ServletFileUpload.isMultipartContent(request));
}

어떤 도움을 주셔서 감사합니다!

미리 감사드립니다.

해결법

  1. ==============================

    1.HTML 표준에 따라 PUT을 통해 양식 데이터를 보낼 수 없습니다. PUT을 통해서만 파일을 보낼 수 있습니다.이 경우 POST를 사용하면 파일을 더 효율적으로 보낼 수 있습니다 (더 이상 모든 멀티 파트 오버 헤드가 없기 때문에).하지만 PUT 수신 서버 측 구성 요소가 실제로 파일을 수신하려면 PUT을 통해 실제로 PUT 명령을 (자바 스크립트를 통해) 보내야합니다. 다음은 JQuery를 사용하는 예제입니다.

    HTML 표준에 따라 PUT을 통해 양식 데이터를 보낼 수 없습니다. PUT을 통해서만 파일을 보낼 수 있습니다.이 경우 POST를 사용하면 파일을 더 효율적으로 보낼 수 있습니다 (더 이상 모든 멀티 파트 오버 헤드가 없기 때문에).하지만 PUT 수신 서버 측 구성 요소가 실제로 파일을 수신하려면 PUT을 통해 실제로 PUT 명령을 (자바 스크립트를 통해) 보내야합니다. 다음은 JQuery를 사용하는 예제입니다.

    $('#file_upload').fileUpload({
        namespace: 'file_upload',
        url: '/path',
        method: 'PUT'
    });
    
  2. ==============================

    2.Spring의 HiddenHttpMethodFilter를 사용하여이를 수행 할 수 있지만, web.xml 필터 체인에서 HiddenHttpMethodFilter 앞에 Spring MultipartFilter를 배치해야합니다.

    Spring의 HiddenHttpMethodFilter를 사용하여이를 수행 할 수 있지만, web.xml 필터 체인에서 HiddenHttpMethodFilter 앞에 Spring MultipartFilter를 배치해야합니다.

    예를 들면 다음과 같습니다. web.xml

    <filter>
        <filter-name>MultipartFilter</filter-name>
        <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
        <init-param>
            <param-name>multipartResolverBeanName</param-name>
            <param-value>filterMultipartResolver</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>MultipartFilter</filter-name>
        <servlet-name>/*</servlet-name>
    </filter-mapping>
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <servlet-name>/*</servlet-name>
    </filter-mapping>
    

    그런 다음 spring-config.xml에서 CommonsMultipartResolver에 대한 참조를 추가하십시오.

    <bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
    

    spring-config.xml 항목을 추가하지 않으면 MultipartFilter는 서블릿 spec 3.0 구현을 사용하는 MultipartResolver를 사용하도록 기본적으로 설정되며 3.0을 사용하지 않는 경우 NoSuchMethodError HttpServletRequest.getParts ()와 같은 오류가 발생합니다.

  3. ==============================

    3.나는 같은 문제를 겪는다. 내 솔루션은 HTTP 메서드 PUT을 통해 보낸 multiparts 수락 ExtendedMultipartResolver 구현했다. CommonsMultipartResolver 코드를 복사하고 클래스의 이름을 바꾸고 isMultipart () 함수의 구현을 필요에 맞게 변경하십시오.

    나는 같은 문제를 겪는다. 내 솔루션은 HTTP 메서드 PUT을 통해 보낸 multiparts 수락 ExtendedMultipartResolver 구현했다. CommonsMultipartResolver 코드를 복사하고 클래스의 이름을 바꾸고 isMultipart () 함수의 구현을 필요에 맞게 변경하십시오.

    private boolean isMultipartContent(HttpServletRequest request) {
      String httpMethod = request.getMethod().toLowerCase();
      // test for allowed methods here...
      String contentType = request.getContentType();
      return (contentType != null && contentType.toLowerCase().startsWith("multipart"));
    }
    
    
    public boolean isMultipart(HttpServletRequest request) {
          return (request != null && isMultipartContent(request));
    }
    

    여기서 POST, PUT 또는 다른 HTTP 메소드를 확인할 수 있습니다. 내 경우에는 모든 방법이 받아 들여지고, 내 컨트롤러 특수 효과가 허용 된 방법으로 필터링됩니다.

    스프링 웹 컨텍스트에서 빈을 설정하는 것을 잊지 마라.

    <bean id="multipartResolver" class="sample.package.ExtendedMultipartResolver"/>
    

    도움이되는 희망.

    건배 크리스

  4. ==============================

    4.http://rugal.ga/development/2015/10/03/uploading-file-other-than-post/에서 영감을 얻은 약간 다른 해결책을 구현했으며 이전 게시물에 가깝습니다.

    http://rugal.ga/development/2015/10/03/uploading-file-other-than-post/에서 영감을 얻은 약간 다른 해결책을 구현했으며 이전 게시물에 가깝습니다.

    public class ExtendedMultipartResolver extends CommonsMultipartResolver {
    
    @Override
    public boolean isMultipart(HttpServletRequest request) {
        return (request != null && isMultipartContent(request));
    }
    
    /**
     * Extends ServletFileUpload.isMultipartContent() behavior to allow PUT requests as multipart.
     * 
     * @param request
     *            The servlet request to be evaluated. Must be non-null.
     *
     * @return <code>true</code> if the request is multipart; <code>false</code> otherwise.
     * @see org.apache.commons.fileupload.servlet.ServletFileUpload#isMultipartContent
     */
    public static final boolean isMultipartContent(HttpServletRequest request) {
        HttpMethod httpMethod = HttpMethod.valueOf(request.getMethod());
        if (HttpMethod.POST != httpMethod && HttpMethod.PUT != httpMethod) {
            return false;
        }
        return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
    }
    

    }

    여기에 새로운 것은 없지만 내 코드는 내용을 복제하는 대신 org.apache.commons.fileupload.FileUploadBase.isMultipartContent (RequestContext)를 사용합니다.

    이제 파일 업로드 서비스의 단위 테스트를 구현해야한다면 org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload ()를 다음과 같이 사용했을 수 있습니다.

    @Test
    public void testUploadFilePost() throws Exception {
        MockMultipartFile multipartFile = new MockMultipartFile(...);
        String url = ...;
        mockMvc.perform(fileUpload(url).file(multipartFile)).andExpect(status().isOk());
    }
    

    org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder가 구현 된 방식 때문에 위의 코드는 POST 요청 만 발행 할 수 있습니다. PUT 파일 업로드를 단위 테스트하려면 다음 코드에 관심이있을 수 있습니다.

    private static final RequestPostProcessor PUT_REQUEST_POST_PROCESSOR = new RequestPostProcessor() {
    
        @Override
        public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
            request.setMethod(HttpMethod.PUT.name());
            return request;
        }
    
    };
    
    private static MockHttpServletRequestBuilder putFileUpload(String url, MockMultipartFile multipartFile,
            Object... urlVariables) {
        return fileUpload(url, urlVariables).file(multipartFile).with(PUT_REQUEST_POST_PROCESSOR);
    }
    

    이제 테스트를 다음과 같이 조정할 수 있습니다.

    @Test
    public void testUploadFilePut() throws Exception {
        MockMultipartFile multipartFile = new MockMultipartFile(...);
        String url = ...;
        mockMvc.perform(putFileUpload(url, multipartFile)).andExpect(status().isOk());
    }
    
  5. from https://stackoverflow.com/questions/7981640/spring-3-0-fileupload-only-with-post by cc-by-sa and MIT license