2

我正在尝试使用 Jersey 制作一个 XSSFWorkbook。

我尝试了以下标题,但似乎没有任何效果:

@Produces("应用程序/xml")

@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")

@Produces("应用程序/vnd.openxml"

全部返回以下错误:

原因:com.sun.jersey.api.MessageException:Java 类 org.apache.poi.xssf.usermodel.XSSFWorkbook 和 Java 类型类 org.apache.poi.xssf.usermodel.XSSFWorkbook 和 MIME 的消息体编写器未找到媒体类型 application/xml ... 37 更多

本质上,我有一个创建 XSSFWorkbook 的函数,我想把它写出来供用户下载。我能够做到这一点:

 /*
    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
    }

但由于其他原因,我还需要返回 XSSFWorkbook 的函数。我希望我可以让泽西写出来,而不是使用网络响应。

感谢您的帮助。

(我对 Jersey 和 XSSF 有点陌生,所以如果我对我的术语或理解不满意,请多多包涵)

4

2 回答 2

2

您需要为 XSSFWorkbook 编写自定义编写器(或找到一个)并将其插入 Jersey 中,例如:

@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 {

然后你必须web.xml像这样将这个类的包添加到你的:

<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 将由您自己的作家来制作这种特定格式。抱歉,我对 XSSFWorkbook 一无所知。

希望能解决您的问题。

于 2012-07-17T18:02:35.787 回答
2

我能够通过 Jersey 返回 StreamingOutput 来解决问题。然后我将 StreamingOutput 的字节写到一个 OutputStream 中。我从 OutputStream 中获得了 byte[],将该 OutputStream 写入 InputStream,然后从该 InputStream 创建了一个新的 XSSFWorkbook。我知道这是一种非常肮脏的做法。我将尝试上面 -Camille R 建议的方式,希望它是一个更清洁的解决方案。但与此同时...

    @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;
      }

关于接收函数:

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();
        }
    }
于 2012-07-17T22:00:27.960 回答