我在尝试验证对 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.
}
}
现在,当我测试不同的场景时:
- 使用
multipart/form-data
调用端点(在attachment
字段中包含文件)可以正常工作。 - 在没有
multipart/form-data
的情况下调用,attachment
字段包含一些文本或不包含文本,正确输入if()
检查对于null
值,但 HTTP 响应变为404 Not Found
,而不是我编码的400 Bad Request
。 - 不带任何字段的调用(空请求),无论是否为
multipart/form-data
,都会触发下面粘贴的NullPointerException
,并返回404未找到
响应。
这是NullPointerException
:
Servlet.service() for servlet [jerseyServlet] in context with path [] threw exception [java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider$FormDataParamValueFactory.provide(FormDataParamValueFactoryProvider.java:205)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:121)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
...
任何想法如何:
- 在情况 (2) 中返回正确的响应 400,并且
- 优雅地处理情况 (3),避免异常并返回代码 400?
最佳答案
最终我们找到了场景 2 的解决方案和场景 3 的解决方法。
场景 2
我们收到的 404 Not Found
响应是由于 Jersey 尝试显示错误页面,而该页面在服务中不存在。通过提供以下配置,可以关闭该默认行为,以便简单地返回所需的错误代码和编码响应:
@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.
}
}
关于java - 在 Spring REST 服务中优雅地处理无效文件上传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31850060/