英文:
Jersey FormDataParam fails with 400 Bad Request
问题
Jersey 和 FormDataParam
在尝试上传图像到我的服务时表现得非常奇怪。我的服务运行在 Dropwizard 上。
接受图像(以及元数据对象)的方法如下:
@POST
@Path("/photos")
@Consumes("multipart/form-data")
fun upload(
@FormDataParam("photo") fileInputStream: FileInputStream,
@FormDataParam("metadata") metadata: PhotoMetadataV1RequestModel
) {
// do something
}
我在 Guice 模块中注册了 MultipartFeature
。
public class JerseyModule extends AbstractModule {
@Override
protected void configure() {
// 其他内容
bind(MultiPartFeature.class).in(Scopes.SINGLETON);
}
}
我在 build.gradle
中添加了 jersey-multipart
依赖项。
// Jersey
compile "org.glassfish.jersey.core:jersey-server:$jerseyVersion"
compile "org.glassfish.jersey.media:jersey-media-multipart:$jerseyVersion"
现在来看有趣的部分。
如果我尝试使用绝对路径上传文件,这实际上是有效的!但是,如果我尝试使用相对路径上传文件,它就无效。
更重要的是,当服务部署在另一台机器上时(不是上传图像请求发出的同一台机器),它也无效。这很重要,因为我将我的服务部署到 Heroku,并且需要从其他地方上传图像!
这是有效的示例(photo
使用绝对路径):
curl --location --request POST "http://localhost:8095/rest/v1/self/photos" \
--header "Authorization: Bearer GaKC8xQju5h" \
--form 'photo=/Users/whizzil/Desktop/nova_scripts/create_users/user-lina/photos-webp/photo-profile-1.webp' \
--form 'metadata={"photoType": "PROFILE", "position": 2};type=application/json'
然而,即使使用这个示例,如果服务器的 URL 不是 localhost,而是 Heroku 服务器等,它仍然无效。
这是无效的示例(photo
使用相对路径):
curl --location --request POST "http://localhost:8095/rest/v1/self/photos" \
--header "Authorization: Bearer GaKC8xQju5h" \
--form 'photo=@./photo-profile-1.webp' \
--form 'metadata={"photoType": "PROFILE", "position": 2};type=application/json'
当它不起作用时抛出的异常:
org.glassfish.jersey.internal.inject.ExtractorException: org.glassfish.jersey.internal.inject.ExtractorException: java.io.FileNotFoundException: Invalid file path
org.glassfish.jersey.media.multipart.FormDataParamException: HTTP 400 Bad Request
at org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider$FormDataParamValueFactory.provide(FormDataParamValueFactoryProvider.java:352)
at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.provide(ParamValueFactoryWithSource.java:71)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:90)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:127)
我感到很困惑。我尝试了谷歌搜索的一切,但没有成功。非常感谢任何帮助!
英文:
I have a very weird behaviour from Jersey and FormDataParam
when trying to upload an image to my service. My service runs on Dropwizard.
The method that accepts an image (along with metadata object) looks like this:
@POST
@Path("/photos")
@Consumes("multipart/form-data")
fun upload(
@FormDataParam("photo") fileInputStream: FileInputStream,
@FormDataParam("metadata") metadata: PhotoMetadataV1RequestModel
) {
// do something
}
I've registered MultipartFeature
in the Guice module.
public class JerseyModule extends AbstractModule {
@Override
protected void configure() {
// other stuff
bind(MultiPartFeature.class).in(Scopes.SINGLETON);
}
}
I've added a jersey-multipart
dependency in the build.gradle
.
// Jersey
compile "org.glassfish.jersey.core:jersey-server:$jerseyVersion"
compile "org.glassfish.jersey.media:jersey-media-multipart:$jerseyVersion"
Now the funny part.
This actually works if I try to upload a file using an absolute path! BUT, it does NOT work I try to upload a file using a relative path.
More importantly, it also does NOT work when a service is deployed on another machine (not the same the upload image request is coming from). This is important, because I deploy my service to Heroku, and I need to upload images from other places!
This is what works (absolute path for the photo
):
curl --location --request POST "http://localhost:8095/rest/v1/self/photos" \
--header "Authorization: Bearer GaKC8xQju5h" \
--form 'photo=/Users/whizzil/Desktop/nova_scripts/create_users/user-lina/photos-webp/photo-profile-1.webp' \
--form 'metadata={"photoType": "PROFILE", "position": 2};type=application/json'
However, even this does NOT work if the url of the server is not localhost, but e.g. Heroku server.
This is what does NOT work (relative path for the photo
):
curl --location --request POST "http://localhost:8095/rest/v1/self/photos" \
--header "Authorization: Bearer GaKC8xQju5h" \
--form 'photo=@./photo-profile-1.webp' \
--form 'metadata={"photoType": "PROFILE", "position": 2};type=application/json'
The exception that is thrown when it doesn't work:
org.glassfish.jersey.internal.inject.ExtractorException: org.glassfish.jersey.internal.inject.ExtractorException: java.io.FileNotFoundException: Invalid file path
org.glassfish.jersey.media.multipart.FormDataParamException: HTTP 400 Bad Request
at org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider$FormDataParamValueFactory.provide(FormDataParamValueFactoryProvider.java:352)
at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.provide(ParamValueFactoryWithSource.java:71)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:90)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:127)
I am lost here. I tried googling everything, but no success. Any help much appreciated!
答案1
得分: 1
Changing FileInputStream
to InputStream
solved the issue. I have no idea why, though.
英文:
Changing FileInputStream
to InputStream
solved the issue. I have no idea why, though.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论