一种解决方案是只读取
InputStream。您可以将包裹在
InputStream中
ZipInputStream。有了,
ZipInputStream您可以得到
ZipEntrywith
ZipInputStream.getNextEntry(),然后可以得到与文件名
ZipEntry.getName()。然后只要检查名称即可
endsWith(".xml")。不过,您需要消耗
application/octet-stream。这是一个简单的例子
@Path("/zip")public class ZipResource { @POST @Consumes(MediaType.APPLICATION_OCTET_STREAM) public Response postZipFile(InputStream is) throws Exception { StringBuilder builder; try (ZipInputStream zip = new ZipInputStream(is)) { builder = new StringBuilder("==== Data ====n"); ZipEntry entry; while ((entry = zip.getNextEntry()) != null) { String filename = entry.getName(); if (filename.endsWith(".xml")) { builder.append("name: ").append(entry.getName()).append("n"); String xml = filePartToString(zip, (int) entry.getSize()); builder.append("data: ").append(xml).append("n"); } zip.closeEntry(); } } return Response.ok(builder.toString()).build(); } private String filePartToString(InputStream is, int size) throws Exception { String xml; byte[] buff = new byte[size]; is.read(buff, 0, size); return new String(buff); }}这是一个测试
@Testpublic void testResteasy() throws Exception { WebTarget target = client.target( TestPortProvider.generateURL(base_URI)).path("zip"); File file = new File("C:/test/test.zip"); Response response = target.request().post( Entity.entity(file, MediaType.APPLICATION_OCTET_STREAM)); System.out.println(response.getStatus()); System.out.println(response.readEntity(String.class)); response.close();}在zip中使用这些文件
test1.xml---------<test1>hello world</test1>test2.xml---------<test2>hello squirrel</test2>test3.json----------{ "test3":"Hello Girls"}我得到以下结果
==== Data ====name: test1.xmldata: <test1>hello world</test1>name: test2.xmldata: <test2>hello squirrel</test2>
顺便说一句,如果您可以控制数据的发送方式,则可能还需要研究多部分解决方案。您可以在其中设置内容类型,并可以命名每个部分,以方便访问它们。
您可以在此处看到Resteasy对multipart的支持以及所需的依赖项。
更新
如果 必须
使用
application/zip,则对此没有标准支持。所以你需要自己动手
MessageBodyReader。它可以像包装并返回已经提供的那样简单
InputStream
@Provider@Consumes("application/zip")public class ZipMessageBodyReader implements MessageBodyReader<ZipInputStream> { @Override public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type == ZipInputStream.class; } @Override public ZipInputStream readFrom(Class<ZipInputStream> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException { return new ZipInputStream(entityStream); } }然后,在您的资源方法中,您可以只具有一个
ZipInputStream参数,而不是
InputStream。
@POST@Consumes("application/zip")public Response postZipFile(ZipInputStream zip) throws Exception {在客户端(使用客户端API),如果要使用
application/zip,则当然还需要编写
MessageBodyWriterfor
application/zip
更新2
注释: 我需要我的方法能够使用一个简单的xml文件和一个包含xml文件的zip归档文件,因此我对方法进行了注释(伪代码):“
consumes(xml,zip)”并声明了一个参数InputStream的方法是;
然后,在方法主体中,我需要确定此InputStream是xml类型还是zip存档,并想要编写类似于以下内容:“
if(is属于xml类型){然后将其视为xml},否则{处理为a zip archive}。希望现在这个问题更容易理解
我们可以让您的原始方法签名接受
application/xml和
application/zip。我们也可以通过注入
HttpHeaders并
Content-Type从中获取来检查实际发送的是哪个。基于此,我们将确定如何提取。这是我们如何完成此操作的另一个示例
@Path("/zip")public class ZipResource { @POST @Consumes({"application/zip", "application/xml"}) public Response postZipFile(InputStream is, @Context HttpHeaders headers) throws Exception { String contentType = headers.getHeaderString(HttpHeaders.CONTENT_TYPE); String returnString = null; if (null != contentType) switch (contentType) { case "application/xml": returnString = readXmlFile(is); break; case "application/zip": returnString = readZipFile(is); break; } return Response.ok(returnString).build(); } private String filePartToString(InputStream is, int size) throws Exception { String xml; byte[] buff = new byte[size]; is.read(buff, 0, size); return new String(buff); } private String readXmlFile(InputStream is) { StringWriter writer = new StringWriter(); try { IOUtils.copy(is, writer, "utf-8"); } catch (IOException ex) { Logger.getLogger(ZipResource.class.getName()).log(Level.SEVERE, null, ex); } return writer.toString(); } private String readZipFile(InputStream is) { StringBuilder builder = new StringBuilder("==== Data ====n"); try (ZipInputStream zip = new ZipInputStream(is)) { ZipEntry entry; while ((entry = zip.getNextEntry()) != null) { String filename = entry.getName(); if (filename.endsWith(".xml")) { builder.append("name: ").append(entry.getName()).append("n"); String xml = filePartToString(zip, (int) entry.getSize()); builder.append("data: ").append(xml).append("n"); } zip.closeEntry(); } } catch (Exception ex) { ex.printStackTrace(); } return builder.toString(); }}我们将需要一个
MessageBodyReader来处理
application/zip类型。上面的一个很好用,但是我们只需要返回一个
InputStream而不是
ZipInputStream
@Provider@Consumes("application/zip")public class ZipMessageBodyReader implements MessageBodyReader<InputStream> { @Override public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type == InputStream.class; } @Override public InputStream readFrom(Class<InputStream> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException { return entityStream; } }现在进行测试
@Testpublic void testResteasy() throws Exception { WebTarget target = client.target( TestPortProvider.generateURL(base_URI)).path("zip"); File file = new File("C:/test/test.zip"); Response response = target.request().post( Entity.entity(file, "application/zip")); System.out.println(response.getStatus()); System.out.println(response.readEntity(String.class)); response.close(); file = new File("C:/test/test1.xml"); response = target.request().post( Entity.entity(file, "application/xml")); System.out.println(response.getStatus()); System.out.println(response.readEntity(String.class)); response.close();}我们得到以下
200==== Data ====name: test1.xmldata: <test1>hello world</test1>name: test2.xmldata: <test2>hello squirrel</test2>200<test1>hello world</test1>
注意:
对于客户端,我必须实现一个
MessageBodyWriter处理
application/zip类型。以下是一个简单的实现,只是为了使测试生效。真正的实现需要一些修复
@Provider@Produces("application/xml")public class ZipClientMessageBodyWriter implements MessageBodyWriter<File> { @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type == File.class; } @Override public long getSize(File t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } @Override public void writeTo(File t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { IOUtils.write(IOUtils.toByteArray(new FileInputStream(t)), entityStream); } }....client.register(ZipClientMessageBodyWriter.class);您还将在一些示例代码中注意到,我使用了Apache Commons
IOUtils。不好意思 我很懒:-)
更新3
实际上,我们不需要
MessageBodyReader。找到读者的算法其实只是默认为
InputStream读者,因为它支持
application/xml,所以它会已经返回
InputStream我们是否有对读者
application/zip还是不



