问题
I am trying to produce a XSSFWorkbook using Jersey.
I have tried the following headers and nothing seems to work:
@Produces("application/xml")
@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
@Produces("application/vnd.openxml"
All return the following error:
Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class org.apache.poi.xssf.usermodel.XSSFWorkbook, and Java type class org.apache.poi.xssf.usermodel.XSSFWorkbook, and MIME media type application/xml was not found ... 37 more
Essentially I have a function which creates the XSSFWorkbook and I would like to write it out for user to download. I am able to do it with:
/*
HttpServletResponse response;
XssfWorkbook excel.write(response.getOutputStream());
*/
@GET
@Path("/excel/")
@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public XSSFWorkbook exportReadingsAsExcel(@Context HttpServletResponse webResponse)
{
XSSFWorkbook excel = createExcel();
setHeader(webResponse, "export.xlsx");
try {
excel.write(webResponse.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
return excel; //ERROR IS HERE
}
But I also need the function to return the XSSFWorkbook for other reasons. And I was hoping instead of using the web response I could have Jersey write it out.
Thank you for your help.
(I am somewhat new to Jersey and XSSF, so please bear with me if I am off on my terminology or understanding)
回答1:
You need to write your custom writer for XSSFWorkbook (or find one) and plug it into Jersey like :
@Provider
@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public class CustomXSSFWorkbookWriter implements MessageBodyWriter {
//This methode is the most important for you
@Override
public void writeTo(Object target, Class type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap httpHeaders, OutputStream outputStream)
throws IOException {
Then you have to add the package of this class to your web.xml
like this :
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.packages.to.your.views;com.packages.to.your.providers</param-value>
</init-param>
Jersey will your your own writer to produce this specific format. Sorry i don't know anything about XSSFWorkbook.
Hopefully will solve your problem.
回答2:
I was able to solve the problem by returning StreamingOutput via Jersey. Then I wrote out the bytes of StreamingOutput into an OutputStream. I got the byte[] from the OutputStream, wrote that OutputStream into the InputStream and then created a new XSSFWorkbook from that InputStream. I know this is a very dirty way of doing it. I will try the way suggested by -Camille R above for what I hope will be a cleaner solution. But in the meantime...
@GET
@Path("/excel/")
@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public StreamingOutput exportReadingsAsExcel(@Context HttpServletResponse webResponse)
{
XSSFWorkbook excel = createExcel();
setHeader(webResponse, "export.xlsx");
StreamingOutput streamOutput = new StreamingOutput(){
public void write(OutputStream output) throws IOException, WebApplicationException {
try {
excel.write(output);
} catch (Exception e) {
throw new WebApplicationException(e);
}
}
};
return streamOutput;
}
On the receiver function:
private XSSFWorkbook createExcel(StreamingOutput mStream){
XSSFWorkbook excel = new XSSFWorkbook();
try {
ExcelOutputStream out = new ExcelOutputStream();
excel.write(out);
ByteArrayInputStream inputStream = new ByteArrayInputStream(out.getBytes());
excel = new XSSFWorkbook(inputStream ;
} catch (WebApplicationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
class MyOutputStream extends OutputStream {
private ByteArrayOutputStream myByteArray;
public MyOutputStream(){
myByteArray = new ByteArrayOutputStream();
}
@Override
public void write(int b) throws IOException {
// TODO Auto-generated method stub
myByteArray.write(b);
}
public byte[] getBytes(){
return myByteArray.toByteArray();
}
}
来源:https://stackoverflow.com/questions/11525510/jersey-produces-apache-xssfworkbook