Jaxrs多部分

10

我正在尝试向媒体类型设置为 multipart/form-data 的jaxrs服务执行请求。此请求包含一个实体(xml)列表和一张图像(png,二进制)。我按照BalusC在这个线程中描述的方式创建了请求。

检查wireshark后,请求似乎没问题,除了ip头校验和不正确(说的是“可能是由IP校验和卸载导致的”)。

我的主要问题在于如何在服务端处理多部分请求。我不希望包括来自apache.cxf、resteasy或任何其他库的任何内容。我只想依赖于jaxrs API。

请求中的两个部分名称分别为deliveriessignature,其中signature是以二进制形式发送的png图像文件。交付列表应该从xml中解析出来(实体具有xmlrootelement注释,因此此部分单独工作)。我尝试了这种读取不同部分的方式,但这真的很玄乎;

@PUT
@Path("signOff")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void signOffDeliveries(@FormParam("deliveries") List<Delivery> deliveries, @FormParam("signature")File signature) {
    //do something with the signature(image) and the list of deliveries.
}

如果我在Websphere上运行请求,这肯定行不通,并且会给我返回404 http状态代码;如果我将请求发送到一个嵌入式的openejb(在我们的集成测试框架中),则会返回415错误。如果我删除FormParam注释,则请求将成功。

如何仅使用jaxrs api读取多部分请求的不同部分?

编辑:好吧,所以我将PUT更改为POST,并向参数添加了@Encoding注释,如下所示:

@POST
@Path("signOff")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void signOffDeliveries(
    @Encoded @FormParam("deliveries") String deliveries,
    @Encoded @FormParam("signature") File signature) {

}

现在我获得了XML格式的文本字符串,但是尽管这部分载荷的Content-Type设置为application/xml,我仍然无法自动解组它为交货列表。另一个问题是,我接收到的文件长度为0,我无法从中读取任何字节。

我是否遗漏了一个重要的点?


规范没有为这种情况提供任何内容。但是jaxrs基于servlet api。使用servlet api,您可以访问请求正文并将其移交给Apache commons FileUpload库https://commons.apache.org/proper/commons-fileupload/。这与jaxrs实现不冲突。 - Christian13467
3个回答

8

实际上,我很难理解为什么JAX-RS规范没有标准化对此的支持(我刚刚创建了https://java.net/jira/browse/JAX_RS_SPEC-413来解决这个问题)。

然而,即使如此,在不依赖于实现的情况下也可以支持多部分表单。你可以编写自己的用于多部分表单的MessageBodyReader,或者使用类库,例如Apache Clerezza jaxrs.utils,该类库提供了一个MultiPartBody对象以及相应的MessageBodyReader。这个类库没有实现规范依赖,因此你的应用程序将运行在任何jax-rs实现上。

关于如何使用Clerezza jaxrs.utils的示例,请参见http://svn.apache.org/viewvc/stanbol/trunk/development/archetypes/stateless-webmodule/src/main/resources/archetype-resources/src/main/java/MultiEnhancer.java?revision=1465777&view=markup中的第105行。如果你没有使用OSGi(通过白板注册资源),则需要将org.apache.clerezza.jaxrs.utils.form.MultiPartFormMessageBodyReader添加到你的应用程序中。


1
在java.net关闭后,JIRA问题去哪了? - Thorbjørn Ravn Andersen
1
看起来JIRA问题已迁移到https://github.com/eclipse-ee4j/jaxrs-api/issues/418。 - Christoph Böhme

1

我已经在Glassfish 4中实现了这一点,而不与Jersey耦合。详见此帖


-2
我不想使用任何来自apache.cxf、resteasy或类似的库。我只想依赖于jaxrs api。
你不能“依赖于”API,因为它只包含接口。实现这些接口的类来自RESTeasy、Jersey或CXF。
当我向嵌入式openejb运行请求时,会返回415错误。
415意味着“方法不支持”,这是由于您向一个期望PUT请求的资源发送了GET请求。
在这种情况下,我建议使用POST而不是PUT。我怀疑在您的特定情况下,@FormParam不适合与PUT一起使用。

8
我知道API只是接口,但只要我不包含任何对Apache CXF特定实现的引用,我应该能够轻松更换容器。然而,将方法更改为POST并没有什么作用。 - Runar Halse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接