我在Response对象中返回StreamingOutput:
@GET
@Path("/downloadFile/{filename}")
@Produces(MediaType.TEXT_PLAIN)
public Response downloadFile(@PathParam("filename") String fileName) {
LOG.debug("called: downloadFile({})", fileName);
final File f = new File("/tmp/" + fileName);
try {
if (f.exists()) {
StreamingOutput so = new StreamingOutput() {
@Override
public void write(OutputStream os) throws IOException,
WebApplicationException {
FileInputStream fis = new FileInputStream(f);
byte[] buffer = new byte[4 * 1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
LOG.debug("streaming file contents @{}", bytesRead);
os.write(buffer, 0, bytesRead);
}
fis.close();
os.flush();
os.close();
}
};
return Response.ok(so, MediaType.TEXT_PLAIN).build();
} else {
return createNegativeXmlResponse("file not found or not readable: '"
+ f.getPath() + "'");
}
} catch (Exception e) {
return handle(e);
}
}
客户端(Junit测试用例):
@Test
public void testDownloadFile() throws Exception {
Client client = ClientBuilder.newBuilder()
.register(MultiPartFeature.class).build();
WebTarget target = client.target(BASE_URI).path("/downloadFile/b.txt");
Response r = target.request(MediaType.TEXT_PLAIN_TYPE).get();
System.out.println(r.getStatus());
Object o = r.readEntity(StreamingOutput.class);
StreamingOutput so = (StreamingOutput) o;
}
服务器在tomcat7实例中运行。当执行r.readEntity时,我在客户端得到的是:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/plain, type=interface javax.ws.rs.core.StreamingOutput, genericType=interface javax.ws.rs.core.StreamingOutput.
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:230)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:154)
...
如何从客户端的Response对象获取StreamingOutput对象?
最佳答案
StreamingOutput
是一个帮助程序类,它使我们可以直接将其写入响应输出流,但并不意味着要从响应中重新创建它,因此没有读取器将字节流转换为StreamingOutput
。我们可以简单地从响应中获取一个InputStream
。
Response response = target.request().get();
InputStream is = response.readEntity(InputStream.class);
完整示例:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
public class TestStreamingOutput extends JerseyTest {
@Path("/streaming")
public static class StreamingResource {
@GET
public StreamingOutput getImage() throws Exception {
final InputStream is
= new URL("http://i.stack.imgur.com/KSnus.gif").openStream();
return new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
byte[] buffer = new byte[4 * 1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.flush();
out.close();
is.close();
}
};
}
}
@Override
protected Application configure() {
return new ResourceConfig(StreamingResource.class);
}
@Test
public void test() throws Exception {
Response response = target("streaming").request().get();
InputStream is = response.readEntity(InputStream.class);
ImageIcon icon = new ImageIcon(ImageIO.read(is));
JOptionPane.showMessageDialog(null, new JLabel(icon));
}
}
仅Maven依赖
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.13</version>
<scope>test</scope>
</dependency>
结果: