java - 如何为 grails 编写 XLSX 自定义渲染器

标签 java excel grails groovy grails-2.0

我正在尝试使用 grails 自定义渲染器来使用 apache-poi 库渲染 Excel XLSX 文件。我做了一个渲染器类

class APIReportXLSXRenderer extends AbstractRenderer<APIReport> {

    APIReportXLSXRenderer() {
        super(APIReport, [new MimeType("application/vnd.ms-excel", "xlsx")] as MimeType[])
    }

    @Override
    void render(APIReport output, RenderContext context) {
        context.contentType = GrailsWebUtil.getContentType("application/vnd.ms-excel", GrailsWebUtil.DEFAULT_ENCODING)

        def items = output.getItems()
        def fields = output.getFields()
        def headers = (fields.keySet() + items[0].keySet()) as List
        // convert maps to list of values each in order of the headers
        def values = (items ?: []).collect { Map item -> headers.collect { String h -> item?.containsKey(h) ? item[h] : output[h] } }
        def wos = new WriterOutputStream(context.writer)
        createXLSXFile(headers, values, wos) // FIXME: This currently produces corrupt files.
    }

    // Lifted from ApiController
    private static def createXLSXFile(List<String> headers = [], List items = [], OutputStream outputStream) {
        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet();
        int rowcount = 0;
        // add header row
        if (headers) {
            Row row = sheet.createRow((short) rowcount++);
            headers.eachWithIndex { String entry, int i ->
                row.createCell(i).setCellValue(entry)
            }
        }

        // add cells
        items?.each { List entry ->
            Row row = sheet.createRow((short) rowcount++);
            entry.eachWithIndex { def value, int i -> row.createCell(i).setCellValue(value as String) }
        }
        wb.write(outputStream);
    }
}

我的 Controller 使用 APIReport 对象进行响应

respond(report)

这似乎会产生一个损坏的文件,但是当我在 Controller 中以相同的方式执行相同的操作时:

withFormat {
                xlsx {
                    def items = output.getItems()
                    def fields = output.getFields()
                    response.setHeader("Content-Type", "application/vnd.ms-excel")
                    response.setHeader("Content-disposition", "attachment; filename=\"${filename}.${params.format}\"")
                    def headers = (fields.keySet() + items[0].keySet()) as List
                    // convert maps to list of values each in order of the headers
                    def values = (items?:[]).collect { headers.collect { String h -> it?.containsKey(h) ? it[h] : output[h] } }
                    createXLSXFile(headers, values, response.outputStream)
                    return
                }
            }

效果很好。

APIReport类如下:

class APIReport extends AbstractMap<String, Object> {

    // request call
    ApiParameters apicall;

    // response
    Map<String, Object> fields;
    Long itemCount;
    List<Map<String, Object>> items;
    Map<String, Object> summary;
}

我在渲染器中做错了什么吗?或者在 grails 2.3.8 中制作自定义渲染器的首选方法是什么

最佳答案

不要使用用于字符数据的 WriterOutputStream,而是使用 BufferedOutputStream 等二进制流将数据写入浏览器

关于java - 如何为 grails 编写 XLSX 自定义渲染器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24271300/

相关文章:

java - XML Schema V 1.1 断言在 Xerces-J 中不起作用

excel - 如何在 Excel 中计算数组的平均斜率?

excel - 字典比较,其中一个键对两列有更多项

java - JSP解析时出错

java - 什么是 XEED?我在哪里可以获得更多相关信息?

java - 不支持的主要.次要版本 52.0 - grails

excel - 为什么此 VBA 代码中的执行未移至错误处理部分

maven-2 - 带有 'mvn clean install' 的 Maven Grails 构建不起作用

validation - chalice 验证已经保存到数据库的数据

ajax - Spring Security 3-Ajax注销