CSV 流式导出

CSV 流式导出

  • CSV 流式导出
      • 实现
      • 处理数据返回ExprotResult
      • 调用CSV的方法导出数据
      • 具体实现
      • 后续

随着业务的不断壮大发展,需要导出的数据量也越来越大!普通的EXCEL导出导出一份上万条的数据可能会用几分钟,十万条和百万条的数据量更是不敢想象,可能直接就OOM了。
所以我们需要找到更快速,减少内存开销的方法来处理导出。
我这里会介绍一种流式处理导出的方法,自己写成了一个通用工具,以便不同的服务调用。

实现

一、获取数据处理成可用的数据
1、实现类需要实现 ExportProcessor
2、查询条件需要继承ExportQuery
API接口:

public interface ExportProcessor<Query extends ExportQuery> {
    ExportResult exectue(Query query);

    default boolean hasNext(Pager page) {
        if (page == null) {
            return false;
        }
        Pager.PageData pageData = page.getPage();
        if (pageData == null) {
            return false;
        }

        return pageData.getTotalPage() > pageData.getCurPage();
    }
}

处理数据返回ExprotResult

@Data
public class ExportResult {
    private boolean hasNext;
    private List> data;
}
ExportResult result = exportResultDataAdapt(mainOrderDataList);
result.setHasNext(hasNext(workOrderDataPager)); // 需要设置是否有下一页

调用CSV的方法导出数据

private final static String WORK_ORDER_FILE_NAME = "工单详情列表";

private final static List HEADS = Lists
        .newArrayList("工单ID", "日期", "城市", "销售点code", "销售点名称", "配送蜂房Code", "配送蜂房", "工单类型", "计划完成时间", "工单状态", "对接OP1",
                "取消时间", "取消原因Code", "取消原因", "取消备注");

ExportFactory.doExport( HttpServletResponse  response, WORK_ORDER_FILE_NAME, HEADS, exportQuery, workOrderExportProcessor);

使用简单的符号标识不同的标题,将某些文字标记为粗体或者斜体,创建一个链接等,详细语法参考帮助?。

本编辑器支持 Markdown Extra ,  扩展了很多好用的功能。具体请参考[Github][2].

具体实现

 /**
     * csv流式导出
     *
     * @param response
     * @param fileName
     * @param heads
     * @param query
     * @param processor
     */
    public static void doExport(
            HttpServletResponse response, String fileName, List heads, ExportQuery query,
            ExportProcessor processor) throws IOException {
        initResponseHead(response, fileName);
        PrintWriter print = response.getWriter();
        //打印表头head
        println(print, heads);
        while (true) {
            ExportResult exportResult = processor.exectue(query);
            if (exportResult == null) {
                break;
            }
            List> data = exportResult.getData();
            //打印每行
            Safes.of(data).forEach(item -> {
                println(print, item);
            });
            if (!exportResult.isHasNext()) {
                break;
            }
        }
        print.flush();
        print.close();
    }

    public static void println(PrintWriter print, List data) {
        logger.info("characters获取到的信息:{}", JsonUtils.toJsonString(characters));
        StringBuilder tmp = new StringBuilder();
        if (CollectionUtils.isEmpty(data)) {
            print.print(tmp.append("\r\n").toString());
            return;
        }
        for (int i = 0; i < data.size(); i++) {
            if (i > 0) {
                tmp.append(",");
            }
            String val = data.get(i);
            if (NumberUtils.isNumber(val) && val.length() > 15) {
                val += "\t";
            }
            if (StringUtils.isNotBlank(val) && CollectionUtils.isNotEmpty(characters)) {
                for (String character : characters) {
                    val = StringUtils.replace(val, character, " ");
                }
            }
            tmp.append(StringUtils.isBlank(val) ? "" : StringUtils.replace(val, ",", "."));
        }

        print.print(tmp.append("\r\n").toString());
    }

    /**
     * 设置头
     *
     * @return
     */
    private static void initResponseHead(HttpServletResponse response, String fileName) {
        if (!StringUtils.endsWith(fileName, ".csv")) {
            fileName += ".csv";
        }
        response.setContentType("application/csv;charset=gb18030");
        try {
            response.setHeader("Content-Disposition",
                    "attachment;filename=\"" + new String(fileName.getBytes(), "ISO8859-1") + "\"");
        } catch (UnsupportedEncodingException e) {
        }
    }

后续

后面会基于注解的方式处理再写一篇~

你可能感兴趣的:(CSV,JAVA)