I'm using Jersey to create RESTful API resources, and ResponseBuilder
to generate the response.
Example code for the RESTful resource:
public class infoResource{
@GET
@Path("service/{id}")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response getCompany(@PathParam("id")String id) {
//company is just a POJO.
Company company = getCompany(id);
return Response.status(200).entity(company).build();
}
}
In the response, it's returning chunked transfer encoding in the response headers. What is the proper way in the "Jersey world" to have it return the Content-Length
header instead of the Transfer-Encoding: chunked
header in the response headers?
Selecting Content-Length
or Transfer-Encoding
is just those Containers choice. It's really a matter of buffer size.
One possible solution is providing a SevletFilter
which buffers all those marshalled bytes and sets Content-Length
header value.
See this page.
@WebFilter
public class BufferFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
final ByteArrayOutputStream buffer =
new ByteArrayOutputStream();
// prepare a new ServletResponseWrapper
// which returns the buffer as its getOutputStream();
chain.doFilter(...)
// now you know how exactly big is your response.
final byte[] responseBytes = buffer.toByteArray();
response.setContentLength(responseBytes.length);
response.getOutputStream().write(responseBytes);
response.flush();
}
@Override
public void destroy() {
}
}
In you class that extends ResourceConfig you can set the buffer size. Responses above this size will be chunked, below will have Content-Length.
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
//your initialization
property(CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 2000000);
}
}
For example, if your inputstream is read from a local file system, just add:
response.header( "Content-Length", file.length() );
Check the full code for a clearer explanation:
@Path("/files")
public class FileDownloadService {
private static final String TXT_FILE = "C:\\your file";
@GET
@Path("/txt")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getTextFile() throws IOException {
File file = new File(TXT_FILE);
FileInputStream inStream = new FileInputStream(file);
ResponseBuilder response = Response.ok((Object) inStream);
response.header("Content-Disposition", "attachment; filename=\"filename\"");
response.header( "Content-Length", file.length() );
return response.build();
}
}
The client side is a Apache HttpClient code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With