2017-10-26 18 views
0

大きなファイルを意図的にダウンロードして例外を取得します。処理コントローラ:スプリングブート。ユーザーにエラーメッセージを返す方法

2017-10-23 14:44:13.635 ERROR 15680 --- [nio-8080-exec-2] s.web.GlobalControllerExceptionHandler : Exception in uploadFile at request http://localhost:8080/painter/uploadFile 

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field uploadfile exceeds its maximum permitted size of 3145728 bytes. 

はとても、クライアントへのメッセージとステータスが渡された例外MultipartException(呼び出しをキャッチ

@ControllerAdvice 
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler implements ErrorViewResolver { 
    private static final Logger LOG = LoggerFactory.getLogger(GlobalControllerExceptionHandler.class); 

    private static final String DEFAULT_ERROR_VIEW = "error"; 

    @ExceptionHandler(value = {MultipartException.class}) 
    @ResponseBody 
    ResponseEntity<?> uploadFile(HttpServletRequest request, MultipartException ex) { 
     LOG.error("Exception in uploadFile at request " + request.getRequestURL(), ex); 
     return new ResponseEntity<String>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); 
    } 


    @ExceptionHandler(value = {Exception.class}) 
    public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) { 
     ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW); 
     LOG.error("Exception at request " + request.getRequestURL(), e); 
     mav.addObject("timestamp", new Date()); 
     mav.addObject("error", e.getMessage()); 
     mav.addObject("path", request.getRequestURL()); 
     return mav; 
    } 

    @Override 
    public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus httpStatus, Map<String, Object> map) { 
     ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW); 
     LOG.error(map.toString()); 
     /** 
     timestamp --- Fri Oct 20 09:46:58 MSK 2017 
     status --- 404 
     error --- Not Found 
     message --- /hudo 
     path --- /hudo 
     **/ 
     map.forEach(mav::addObject); 
     return mav; 
    } 
} 

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST, produces={"application/text; charset=UTF-8"}) 
@ResponseBody 
public ResponseEntity<?> uploadFile(
     @RequestParam("uploadfile") MultipartFile uploadfile) throws Exception { 
    String fileName = storageService.uploadFile(uploadfile); 
    return new ResponseEntity<String>(fileName, HttpStatus.OK); 
} 

私は、グローバルインターセプタを持っていますアヤックスにいた)。答えは:

POST http://localhost:8080/painter/uploadFile net::ERR_CONNECTION_ABORTED 
status - 0 error - undefined 

どのようにしてインターセプタからの応答を得ることができますか?

+0

どのLOG.errorが呼び出されていますか、どの例外メソッドが呼び出されていますか? –

+0

エラーログ(大きなもの)自分のクライアントにメッセージを返す必要がある場合はどうすればいいですか?たとえば、「あなたのファイルは3MBの最大値を超えています。メソッドは値= {MultipartException.class}で呼び出されます – Aleksandr

+0

https://stackoverflow.com/a/46655226/3530898 –

答えて

0

私はExceptionHandlerの問題について小さな実験を行いました。簡単にするために、メソッド入力としてPOJOを使用したので、Postmanまたはcurlを使って簡単にテストすることができました。私のアプローチをあなたのMultiPartFile入力に適用しようとすることができます。ここで部品である:

**pom.xml**

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.5.7.RELEASE</version> 
    </parent> 

    <groupId>com.test</groupId> 
    <artifactId>test-app</artifactId> 
    <version>1.0-SNAPSHOT</version> 
    <packaging>war</packaging> 

    <build> 
     <plugins> 
      <plugin> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <configuration> 
        <source>1.8</source> 
        <target>1.8</target> 
       </configuration> 
      </plugin> 

      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId> 

      </plugin> 
      <plugin> 
       <artifactId>maven-resources-plugin</artifactId> 
       <version>2.6</version> 

      </plugin> 
      <plugin> 
       <artifactId>maven-assembly-plugin</artifactId> 
       <configuration> 
        <descriptorRefs> 
         <descriptorRef>jar-with-dependencies</descriptorRef> 
        </descriptorRefs> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
    <dependencies> 

     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-test</artifactId> 
      <version>4.3.11.RELEASE</version> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-logging</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-test</artifactId> 
      <scope>test</scope> 
     </dependency> 

    </dependencies> 
</project> 

スプリングブートアプリ @SpringBootApplicationパブリッククラスTestApplicationはSpringBootServletInitializer {

private static final Logger log = LoggerFactory.getLogger(TestApplication.class); 

@Autowired 
Environment env; 

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

@Override 
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 
    return application.sources(TestApplication.class); 
} 

@Bean 
public ConversionService conversionService() { 
    return new DefaultConversionService(); 
} 

}

コントロールを拡張しますLER

@RestController 
@RequestMapping("/api") 
public class TestController { 

    @RequestMapping(value = "/upload", method = RequestMethod.POST, produces={"application/json"}) 
    @ResponseBody 
    @ResponseStatus(HttpStatus.OK) 
    public TestResponse uploadFile(@RequestBody TestRequest request) throws MultipartException { 
     if ("danger.txt".equalsIgnoreCase(request.getFileName())) { 
      throw new MultipartException("Danger. Get outta there now!"); 
     } else { 
      return new TestResponse("all good"); 
     } 
    } 
} 

例外ハンドラ

@ControllerAdvice 
public class GlobalExceptionHandler { 

    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class); 

    @ExceptionHandler(value = {MultipartException.class}) 
    @ResponseBody 
    ResponseEntity<ErrorResponse> handleFileUploadException(HttpServletRequest request, MultipartException ex) { 
     LOG.error("Exception in uploadFile at request " + request.getRequestURL(), ex); 
     ErrorResponse response = new ErrorResponse("Dangerous file", "The file was pretty scary."); 
     return new ResponseEntity<ErrorResponse>(response, HttpStatus.INTERNAL_SERVER_ERROR); 
    } 
} 

リクエスト/レスポンスのPOJO

public class TestRequest { 

    private String fileName; 

    public TestRequest() { 

    } 

    public TestRequest(String fileName) { 
     this.fileName = fileName; 
    } 

    public String getFileName() { 
     return fileName; 
    } 

    public void setFileName(String fileName) { 
     this.fileName = fileName; 
    } 
} 

public class TestResponse { 

    private String message; 

    public TestResponse() { 

    } 

    public TestResponse(String message) { 
     this.message = message; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 
} 

エラー応答POJO

import com.fasterxml.jackson.annotation.JsonProperty; 

public class ErrorResponse { 

    @JsonProperty("error") 
    private String error; 

    @JsonProperty("error_description") 
    private String errorDescription; 

    public ErrorResponse() { 

    } 

    public ErrorResponse(String error, String errorDescription) { 
     super(); 
     this.error = error; 
     this.errorDescription = errorDescription; 
    } 

    public String getError() { 
     return error; 
    } 

    public String getErrorDescription() { 
     return errorDescription; 
    } 

} 

私はmvn spring-boot:runでアプリを実行しました。その後、curlを使用してAPIをテストしました。

カール要求

curl -d '{"fileName":"danger.txt"}' -H "Content-Type: application/json" -X POST http://localhost:8080/api/upload -v 

カール応答

Note: Unnecessary use of -X or --request, POST is already inferred. 
* timeout on name lookup is not supported 
* Trying ::1... 
    % Total % Received % Xferd Average Speed Time Time  Time Current 
           Dload Upload Total Spent Left Speed 
    0  0 0  0 0  0  0  0 --:--:-- --:--:-- --:--:--  0* Connected to localhost (::1) port 8080 (#0) 
> POST /api/upload HTTP/1.1 
> Host: localhost:8080 
> User-Agent: curl/7.49.1 
> Accept: */* 
> Content-Type: application/json 
> Content-Length: 25 
> 
} [25 bytes data] 
* upload completely sent off: 25 out of 25 bytes 
< HTTP/1.1 500 
< Content-Type: application/json;charset=UTF-8 
< Transfer-Encoding: chunked 
< Date: Fri, 27 Oct 2017 07:07:26 GMT 
< Connection: close 
< 
{ [81 bytes data] 
100 100 0 75 100 25 2343 781 --:--:-- --:--:-- --:--:-- 2343{"error":"Dangerous file","error_description":"The file was pretty scary."} 
* Closing connection 0 

最後に、私は、必要に応じて、適切なHTTP 500とクライアントを簡単に解析できるカスタム応答メッセージが表示されます。

+0

あなたのメソッドをありがとう、ありがたいことに私のケースでは効果がありませんでした。結果は変わりません。 – Aleksandr

関連する問題