Dropwizard FileNotFoundException 当文件存在并被调试器看到时

Dropwizard FileNotFoundException whilst the file is present and seen by debugger

我正在测试使用 dropwizard 构建的端点,但出了点问题:

@Test
public void testPostWithFileSuccess() throws Exception
{
    FileDataBodyPart filePart = new FileDataBodyPart("file", new File(fixture("resources/testImage.jpg")));
    filePart.setContentDisposition(FormDataContentDisposition.name("file").fileName("testImage.jpg").build());

    FormDataMultiPart request = new FormDataMultiPart();
    request.field("data", fixture("resources/postWithFileSuccess.json"), MediaType.APPLICATION_JSON_TYPE);
    request.bodyPart(filePart);

    WebTarget target = mClient.target("http://localhost:8080/crackers").register(MultiPartFeature.class);
    Response response = target
            .request()
            .post(Entity.entity(request, MediaType.MULTIPART_FORM_DATA));

    assertThat(response.getStatus()).isEqualTo(200);
}

实际发生的是测试在 .post(Entity.entity(request, MediaType.MULTIPART_FORM_DATA)); 上失败,预期如下:

javax.ws.rs.ProcessingException: java.io.FileNotFoundException: Invalid file path at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:287) at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:252) at org.glassfish.jersey.client.JerseyInvocation.call(JerseyInvocation.java:684) at org.glassfish.jersey.client.JerseyInvocation.call(JerseyInvocation.java:681) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:228) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444) at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681) at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437) at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:343) at org.example.project.resources.CrackersTest.testPostWithFileSuccess(CrackersTest.java:201) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.rules.ExternalResource.evaluate(ExternalResource.java:48) at org.junit.rules.RunRules.evaluate(RunRules.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner.run(ParentRunner.java:238) at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access[=16=]0(ParentRunner.java:53) at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.junit.runner.JUnitCore.run(JUnitCore.java:160) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) Caused by: java.io.FileNotFoundException: Invalid file path at java.io.FileInputStream.(FileInputStream.java:133) at org.glassfish.jersey.message.internal.FileProvider.writeTo(FileProvider.java:115) at org.glassfish.jersey.message.internal.FileProvider.writeTo(FileProvider.java:67) at org.glassfish.jersey.media.multipart.internal.MultiPartWriter.writeTo(MultiPartWriter.java:232) at org.glassfish.jersey.media.multipart.internal.MultiPartWriter.writeTo(MultiPartWriter.java:79) at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:265) at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250) at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1130) at org.glassfish.jersey.client.ClientRequest.doWriteEntity(ClientRequest.java:517) at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:499) at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:388) at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285) ... 42 more

我不太确定,好像文件不存在或者路径是错误的,Exception 会在 new File(...) 声明中抛出。

filePart显然有问题,但是什么?如果我注释掉 request.bodyPart(filePart);,测试就会失败并出现比较错误(这是预期的)。

问题是 fixture(...) 方法 returns Resources.toString(Resources.getResource(filename), charset).trim(),因此调试器可以看到该文件,但 post(...) 无法处理它。

要解决此问题,而不是

new File(fixture("resources/testImage.jpg"))

我应该用

new File(Resources.getResource("resources/testImage.jpg").toURI())

完整的固定方法列表:

@Test
public void testPostWithFileSuccess() throws Exception
{
    FileDataBodyPart filePart = new FileDataBodyPart("file", new File(Resources.getResource("resources/testImage.jpg").toURI()));
    filePart.setContentDisposition(FormDataContentDisposition.name("file").fileName("testImage.jpg").build());

    FormDataMultiPart request = new FormDataMultiPart();
    request.field("data", fixture("resources/postWithFileSuccess.json"), MediaType.APPLICATION_JSON_TYPE);
    request.bodyPart(filePart);

    WebTarget target = mClient.target("http://localhost:8080/crackers").register(MultiPartFeature.class);
    Response response = target
            .request()
            .post(Entity.entity(request, MediaType.MULTIPART_FORM_DATA));

    assertThat(response.getStatus()).isEqualTo(200);
}