2016-08-17 3 views
6

스프링 부트 스톰 패스 1.0.2와 함께 스프링 부트 버전 = '1.4.0.RC1'을 사용하고 있습니다.스프링 부트 멀티 파트 파일은 항상 null

멀티 파트 파일 업로드를 사용하려하지만 MultipartFile은 컨트롤러에서 항상 null입니다.

나는 ("파일")는 정보 @RequestPart를 사용하는 경우 : "status":400,"error":"Bad Request","exception":"org.springframework.web.multipart.support.MissingServletRequestPartException","message":"Required request part 'file' is not present" 나는 (= 거짓 필요한 이름 = "파일") @RequestPart를 사용하는 경우, 부품이 항상 null의

.

그러나 컨트롤러에 HttpServletRequest 인수를 추가하면 파일 부분을 요청에서 직접 가져올 수 있으므로 실제로 존재한다는 것을 알 수 있습니다.

이것은 컨트롤러 및 checkNotNull(part) 아래의 코드는 항상 성공하고 checkNotNull(imageFile)는 항상 실패

@Multipart 
@POST("users/{username}/profilePhoto") 
Call<Void> uploadProfilePhoto(@Path("username") String username, 
           @Part("file") RequestBody profilePhoto); 

... 

@Test 
public void saveProfilePhoto_shouldSavePhoto() throws IOException { 
    // Given 
    String usernamme = usernames[0]; 
    Resource testImageResource = context.getResource("classpath:images/test_image.jpg"); 
    File imageFile = testImageResource.getFile(); 
    RequestBody body = RequestBody.create(okhttp3.MediaType.parse("image/*"), imageFile); 

    // When 
    Response<Void> response = getTestApi().uploadProfilePhoto(usernamme, body).execute(); 

    // Then 
    assertThat(response.code()).isEqualTo(201); 
} 

내가 자동 구성을 내 유일한 정의 있도록 사용하고 있습니다 :

@PostMapping("{username}/profilePhoto") 
public ResponseEntity<?> saveProfilePhoto(@PathVariable("username") String username, 
              @RequestPart(name = "file", required = false) MultipartFile imageFile, 
              HttpServletRequest request) { 
    try { 
     Part part = request.getPart("file"); 
     checkNotNull(part); 
     checkNotNull(imageFile); 
    } catch (IOException | ServletException ex) { 
     throw InternalServerErrorException.create(); 
    } 

    // Transfer the multipart file to a temp file 
    File tmpFile; 
    try { 
     tmpFile = File.createTempFile(TMP_FILE_PREFIX, null); 
     imageFile.transferTo(tmpFile); 
    } catch (IOException ex) { 
     log.error("Failed to create temp file", ex); 
     throw InternalServerErrorException.create(); 
    } 

    // Execute the use case 
    updateUserProfilePhoto.execute(username, tmpFile); 

    // Delete the temp file 
    FileUtils.deleteQuietly(tmpFile); 

    return ResponseEntity.status(HttpStatus.CREATED).build(); 
} 

내 통합 테스트는 개조가 사용 구성 클래스는 스톰 패스를 구성합니다.

@Configuration 
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.apply(stormpath()); 
    } 
} 

업데이트 : 발신 요청입니다. 멀티 파트 분석기 자체에서 로깅을 활성화하는 방법을 잘 모르겠습니다.

2016-08-18 14:44:14.714 DEBUG 13088 --- [   main] c.t.server.web.testutil.TestConfig$1  : --> POST http://localhost:8080/users/user1/profilePhoto http/1.1 
2016-08-18 14:44:14.714 DEBUG 13088 --- [   main] c.t.server.web.testutil.TestConfig$1  : Content-Type: multipart/form-data; boundary=fe23ef21-3413-404c-a260-791c6921b2c6 
2016-08-18 14:44:14.715 DEBUG 13088 --- [   main] c.t.server.web.testutil.TestConfig$1  : Content-Length: 181212 
2016-08-18 14:44:14.715 DEBUG 13088 --- [   main] c.t.server.web.testutil.TestConfig$1  : Accept: application/json 
2016-08-18 14:44:14.715 DEBUG 13088 --- [   main] c.t.server.web.testutil.TestConfig$1  : Authorization: Bearer [token] 
2016-08-18 14:44:14.715 DEBUG 13088 --- [   main] c.t.server.web.testutil.TestConfig$1  : 
2016-08-18 14:44:14.735 DEBUG 13088 --- [   main] c.t.server.web.testutil.TestConfig$1  : --fe23ef21-3413-404c-a260-791c6921b2c6 
Content-Disposition: form-data; name="file" 
Content-Transfer-Encoding: binary 
Content-Type: image/* 
Content-Length: 180999 

file data 

--fe23ef21-3413-404c-a260-791c6921b2c6-- 

2016-08-18 14:44:14.762 DEBUG 13088 --- [   main] c.t.server.web.testutil.TestConfig$1  : --> END POST (181212-byte body) 

무슨 일이 일어나고 있는지 아이디어가 있습니까?

+0

요청 페이로드의 모양을 포함 할 수 있습니까? 디버그 레벨 로깅을 요청의 multipart 구성 요소를 해석하는지 확인하기 위해 사용중인'MultipartResolver'에 추가 할 수 있습니까? –

+0

@ shawn-clark 이것은 나가는 요청입니다. 멀티 파트 분석기 자체에서 로깅을 활성화하는 방법을 잘 모르겠습니다. 요청 헤더 : 수락 : 애플리케이션/JSON 권한 : 베어러 [인증 토큰] 요청 본문 : --56436527-d311-4d26-8e67-27fdf6f0edb8 내용 - 처리 : 폼 데이터; = "파일" 콘텐츠 전송 인코딩 이름 : 진 내용 - 형식 : 이미지/* 콘텐츠 길이 : 180,999 [... 진 ...] --56436527-d311-4d26-8e67- 27fdf6f0edb8-- – JabariP

+0

스프링 부트 1.4를 사용하고 있기 때문에 내 솔루션을 사용할 수 있습니다. – rajadilipkolli

답변

1

내가 문제가 내가 Retrofit으로 요청을 작성하는 방식이라는 것을 알았습니다.

봄의 여러 부분 해결 파일이 부분의 내용 - 처리 필드에 존재하는 파일명이 필요합니다. 이 옵션이 없으면 파일을 다중 요청에 추가하지 않습니다.

가 정보에 따르면 여기 : https://futurestud.io/blog/retrofit-2-how-to-upload-files-to-server, 내 API 인터페이스는해야한다 : 다음

@Multipart 
@POST("users/{username}/profilePhoto") 
Call<Void> uploadProfilePhoto(@Path("username") String username, 
           @Part MultipartBody.Part profilePhoto); 

그리고 내 시험에서 전화 할 때 :

// Given 
String usernamme = usernames[0]; 
Resource testImageResource = context.getResource("classpath:images/test_image.jpg"); 
File imageFile = testImageResource.getFile(); 
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile); 
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", imageFile.getName(), requestFile); 

// When 
Response<Void> response = testApi.uploadProfilePhoto(usernamme, filePart).execute(); 
+0

다행입니다. 나는 생각하고 있었지만 샘플 요청은 "파일"이라는 이름이 있음을 보여줍니다. –

2

기본적으로 Spring Multipart Resolver을 활성화해야합니다. 스프링은 멀티 파트 기능을 활성화하지 않습니다.

일부 개발자 은 멀티 파트 자체를 처리하기 때문에 기본적으로 Spring은 다중 부분 처리를하지 않습니다. 웹 응용 프로그램의 컨텍스트에 멀티 파트 해결 프로그램을 추가하여 스프링 멀티 파트 처리를 활성화합니다. 구성 클래스에

다음 빈을 추가 할 것입니다 :

@Bean 
public MultipartResolver multipartResolver() { 
    return new CommonsMultipartResolver(); 
} 

* 내 이전 응답으로 업데이트 * 는 의견에 따라 수정되지 않았습니다. 다음은 성공적으로 실행할 수있는 업데이트 된 예제입니다.

@SpringBootApplication 
public class StackoverflowWebmvcSandboxApplication { 
    public static void main(String[] args) { 
     SpringApplication.run(StackoverflowWebmvcSandboxApplication.class, args); 
    } 

    @Controller 
    public class UploadPhoto { 
     @PostMapping("{username}/profilePhoto") 
     public ResponseEntity<String> saveProfilePhoto(@PathVariable("username") String username, 
       @RequestPart(name = "file", required = false) MultipartFile imageFile, HttpServletRequest request) { 
      String body = "MultipartFile"; 
      if (imageFile == null) { 
       body = "Null MultipartFile"; 
      } 

      return ResponseEntity.status(HttpStatus.CREATED).body(body); 
     } 
    } 
} 

특별한 것들이없는 매우 기본적인 테스트입니다. 나는 다음 우편 배달부 요청을 생성하고 여기에 샘플 컬 호출입니다 :

curl -X POST -H "Cache-Control: no-cache" -H "Postman-Token: 17e5e6ac-3762-7d45-bc99-8cfcb6dc8cb5" -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" -F "[email protected]" "http://localhost:8080/test/profilePhoto" 

응답은 MultipartFile가 null가 아닌 것을 의미하고 그 라인에 디버그를하고 있었다 변수가 이미지로 채워 것을 보여 주었다 I 업로드 중입니다.

+0

스프링 부트 웹 MVC는 다중 파트 리졸버를 자동으로 구성하므로 해당 콩을 추가 할 필요가 없습니다. 수표로, 나는 그것을 추가했지만 여전히 같은 오류가 발생했습니다. – JabariP

+0

Ah nice ... 자동 구성을 확인하지 않았지만'MultipartAutoConfiguration'에서 찾았습니다. 기본적으로'StandardServletMultipartResolver'를 사용합니다. 당신은 여전히'CommonsMultipartResolver'로 에러를 얻고 있다고 말했습니다. 요청이 들어오는 방식에 문제가있는 것 같습니다. –

0

을 당신은 Spring Multipart Resolver 등을 활성화해야 기본적으로 Spring은 다중 부분 기능을 활성화하지 않습니다.

일부 개발자 은 멀티 파트 자체를 처리하기 때문에 기본적으로 Spring은 다중 부분 처리를하지 않습니다. 웹 응용 프로그램의 컨텍스트에 멀티 파트 해결 프로그램을 추가하여 스프링 멀티 파트 처리를 활성화합니다. 구성 클래스에

다음 빈 추가 할 것입니다 : 봄 부팅 1.4은 서블릿을 사용

@Bean 
public MultipartResolver multipartResolver() { 
    return new StandardServletMultipartResolver(); 
} 

때문에 우리가 대신 고전 CommonsMultipartResolver

+0

가 문제를 해결하지 못함 – AutoMEta

+0

어떤 버전의 스프링 부트를 사용하고 있습니까? – rajadilipkolli

+0

https : // github./ 작동하지 않는 샘플 코드/LVM-L112 샘플 코드/mkc/configuration/WebMvcConfig.java # L99-L112 – rajadilipkolli

0

StandardServletMultipartResolver에 활용할 수 3.0 이상을 참조하십시오 내 대답은 다음 URL을 참조하십시오 : Spring Boot multipart upload getting null file object

기본적으로 기본 구성을 피하십시오 이온을 사용하여 요청 헤더에 Content-type 또는 boundary를 설정하지 마십시오.

관련 문제