Jersey @Produces Apache XSSFWorkbook

人盡茶涼 提交于 2019-12-22 12:14:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!