Issue
I have a Servlet which makes a request to my Rest API, and I want it to return the API Response content to the final user through the HttpServletResponse.
The content is actually a .xls file to download which I put in the Response with the StreamingOutput Object.
How can I do that ? I can't cast the Response into a HttpServletResponse
Rest API method :
@GET
@Produces( MediaType.APPLICATION_JSON )
@Path("bla")
public Response getTopicByName() {
final Workbook wb = new HSSFWorkbook();
StreamingOutput stream = new StreamingOutput() {
@Override
public void write(OutputStream output) throws IOException, WebApplicationException {
wb.write(output);
}
};
responseBuilder = responseBuilder.entity(stream);
responseBuilder = responseBuilder.status(Response.Status.OK);
responseBuilder = responseBuilder.header("Content-Disposition", "attachment; filename=" + device + ".xls");
return responseBuilder.build();
}
Servlet POST method :
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(url);
Response res = target. request().get();
if (res.getStatus() == 200) {
// how to put res stream into response stream ?
ServletOutputStream stream = response.getOutputStream();
}
client.close();
}
EDIT :
I tried TedTrippin method and after finding out the way to recover an InputStream from the Response, it worked well.
But I keep getting corrupted xls files. And it is quite annoying. I don't get those corrupted files when I make the request directly from the browser. Got any clues where it comes from ?
POST method :
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(url + param + format);
Response res = target.request().get();
if (res.getStatus() == 200) {
response.setHeader("Content-Disposition", "attachment; filename=test.xls");
InputStream in = res.readEntity(InputStream.class);
ServletOutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
while (in.read(buffer) >= 0) {
out.write(buffer);
}
out.flush();
}
client.close();
}
Solution
Simplest way is to read the response stream and write it straight to the response output stream. Either use a library function from IOUtils or Guava or pure java...
try (InputStream in = ...;
OutputStream out = ...) {
byte[] buffer = new byte[1024];
while (in.read(buffer) >= 0)
out.write(buffer);
} catch (IOException ex) {
...
}
A nicer (depending on your view) way would be to read/save the response as a temporary file then you could return that or write it to the output stream.
Third approach would be to create a pipe, but I don't think that would be applicable here.
Answered By - TedTrippin