我在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>

结果:

10-06 16:08