在Spring REST服务中优雅地处理无效文件上传

时间:2015-08-06 08:01:09

标签: java spring rest jersey multipartform-data

我遇到了一个障碍,试图验证REST端点上传文件的请求。只要请求正确,上传工作正常,现在我想包括检查所需字段是否存在以及它们包含的数据是否是我所期望的。

我使用Spring Boot 1.2.5和jersey-media-multipart 2.1.4。

这是服务:

@Service
@Path("/attachments")
public class AttachmentsController {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response upload(@FormDataParam("attachment") InputStream attachmentInputStream,
                           @FormDataParam("attachment") FormDataContentDisposition attachmentFileDetail) {

        if (null == attachmentInputStream
                || null == attachmentFileDetail
                || null == attachmentFileDetail.getFileName()) {
            return Response.status(Response.Status.BAD_REQUEST).build();
        }

        // receiving, storing file, returning 201 Created responses etc.
    }

}

现在,当我测试不同的场景时:

  1. 使用multipart/form-data调用端点,其中包含attachment字段中的文件。
  2. 在没有multipart/form-data的情况下进行呼叫,attachment字段包含一些文本或没有该文本,正确输入if()检查null值,但HTTP响应变为{{ 1}}而不是我编码的404 Not Found
  3. 在没有任何字段(空请求)的情况下进行呼叫,无论是400 Bad Request,都会触发下面粘贴的multipart/form-data,并返回NullPointerException响应。
  4. 这里是404 Not Found

    NullPointerException

    任何想法如何:

    1. 在情况(2)中返回正确的响应400,并且
    2. 优雅地处理案例(3),避免异常并返回代码400?

2 个答案:

答案 0 :(得分:0)

关于方案3:

也许您可以配置NullPointerException以产生400?

@ControllerAdvice
class GlobalControllerExceptionHandler {
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(NullPointerException .class)
    public void handleNull() {
        // Nothing to do
    }
}

答案 1 :(得分:0)

最后,我们找到了方案2的解决方案和3的解决方法。

场景2

我们得到的404 Not Found回复是由于泽西岛试图显示错误页面,该页面在服务中并不存在。可以关闭该默认行为,有利于通过提供以下配置简单地将所需的错误代码与编码响应一起返回:

@Component
public class WebServiceConfig extends ResourceConfig {

    public WebServiceConfig() {
        property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true");
    }
}

场景3

我们通过为POST个请求添加第二个服务方法(下面名为uploadBodyMissing),期望没有参数。因此,如果没有参数POST进入,则会调用此参数并返回400 Bad Request响应:

@Service
@Path("/attachments")
public class AttachmentsController {

    @POST
    @Consumes(MediaType.TEXT_PLAIN)
    public Response uploadBodyMissing() {
        return Response.status(Response.Status.BAD_REQUEST).build();
    }

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response upload(@FormDataParam("attachment") InputStream attachmentInputStream,
                           @FormDataParam("attachment") FormDataContentDisposition attachmentFileDetail) {

        if (null == attachmentInputStream
                || null == attachmentFileDetail
                || null == attachmentFileDetail.getFileName()) {
            return Response.status(Response.Status.BAD_REQUEST).build();
        }

        // receiving, storing file, returning 201 Created responses etc.
    }

}