当前位置:   article > 正文

SpringMVC在内存中直接生成Excel让用户在浏览器中直接下载使用

spring 生成excel不存本地直接下载

1. 如何查询出数据库的SCHEMA, 这里贴出核心的SQL语句

  1. SELECT COLUMN_NAME AS field, COLUMN_COMMENT AS comment
  2. FROM INFORMATION_SCHEMA.COLUMNS
  3. WHERE table_name = ?



由于注释有的会很长, 全部取出来作为excel的一格, 会很不好, 其实我们只是需要重要的意思, 所以, 这里前提条件就是将注释用分隔符分开

例如: name=>名称: 用户昵称, 这里我就可以用":"来分割, 只取出"名称"来. 所以, 一件方便的事情是需要很多的约定的, 尤其是团队合作中.

为了拿到一张表的字段名, 和注释, 就提取了一个公用的类:

  1. /**
  2. * Created with antnest-platform
  3. * User: Vernon.Chen
  4. * Date: 2015/3/16
  5. * Time: 17:03
  6. */
  7. @Service
  8. public class QuerySchema {
  9. @Resource
  10. private JdbcTemplate jdbcTemplate;
  11. public List<Map<String, Object>> getSchemaByTableName(String tableName) {
  12. if (StringUtils.isBlank(tableName)) {
  13. return null;
  14. }
  15. List<Map<String, Object>> schema = new ArrayList<Map<String, Object>>();
  16. StringBuilder sqlSB = new StringBuilder();
  17. sqlSB.append(" SELECT COLUMN_NAME AS field, COLUMN_COMMENT AS comment ");
  18. sqlSB.append(" FROM INFORMATION_SCHEMA.COLUMNS ");
  19. sqlSB.append(" WHERE table_name = ? ");
  20. schema = jdbcTemplate.queryForList(sqlSB.toString(), new Object[]{tableName});
  21. if (schema != null && schema.size() > 0) {
  22. for (Map<String, Object> map : schema) {
  23. String comment = (String) map.get("comment");
  24. if (StringUtils.isNotBlank(comment) && comment.indexOf(":") > -1) {
  25. map.put("comment", comment.substring(0, comment.indexOf(":")));
  26. }
  27. }
  28. }
  29. return schema;
  30. }
  31. }



这返回的结果就是一List, 里面每一个Map都是一个{"field":"XXX","comment":"XXX"}.

下面就是如何生成Excel呢? 也是比较总要的一步. 生成Excel我所知道jar包有2个, 一个是jxl.jar, 还有一个就是项目中用到的poi.

  1. <dependency>
  2. <groupId>org.apache.poi</groupId>
  3. <artifactId>poi</artifactId>
  4. <version>${poi.version}</version>
  5. </dependency>



这里我的版本是: 
<poi.version>3.10-FINAL</poi.version>

然后开看一个组装Excel的代码. 由于不需要将生成的文件持久化到本地, 所以直接返回byte[]就好.

  1. @Override
  2. public byte[] selectExcel() throws Exception {
  3. ByteArrayOutputStream out = null;
  4. try {
  5. HSSFWorkbook workbook = new HSSFWorkbook();
  6. generateExcelForAs(cellMapper.selectExcel(), workbook);
  7. out = new ByteArrayOutputStream();
  8. HSSFWorkbook hssWb = (HSSFWorkbook) workbook;
  9. hssWb.write(out);
  10. } catch (IOException e) {
  11. e.printStackTrace();
  12. } finally {
  13. if (out != null) {
  14. try {
  15. out.close();
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. }
  19. }
  20. }
  21. return out.toByteArray();
  22. }



迭代生成每一行
  1. private void generateExcelForAs(List<Map<String, Object>> list, HSSFWorkbook workbook) {
  2. if (list == null || list.size() == 0) {
  3. return ;
  4. }
  5. List<Map<String, Object>> title = querySchema.getSchemaByTableName("t_cell");
  6. int excelRow = 0;
  7. try {
  8. HSSFSheet sheet = workbook.createSheet();
  9. for (int i = 0; i < list.size(); i++) {
  10. if (i == 0) {
  11. Map<String, Object> first = list.get(0);
  12. // 添加标题
  13. int column = 0;
  14. HSSFRow row = sheet.createRow(excelRow);
  15. for (Map<String, Object> map : title) {
  16. row.createCell(column).setCellValue(map.get("comment").toString());
  17. column++;
  18. }
  19. excelRow++;
  20. column = 0;
  21. // 还需添加第1行的数据, 从0开始
  22. row = sheet.createRow(excelRow);
  23. for (Map<String, Object> map : title) {
  24. if (!first.containsKey(map.get("field"))) {
  25. column++;
  26. } else {
  27. String value = first.get(map.get("field")) == null ? "" : first.get(map.get("field")).toString();
  28. row.createCell(column).setCellValue(value);
  29. column++;
  30. }
  31. }
  32. excelRow++;
  33. } else {
  34. HSSFRow row = sheet.createRow(excelRow);
  35. Map<String, Object> rowMap = list.get(i);
  36. int column = 0;
  37. for (Map<String, Object> map : title) {
  38. if (!rowMap.containsKey(map.get("field"))) {
  39. column++;
  40. } else {
  41. String value = rowMap.get(map.get("field")) == null ? "" : rowMap.get(map.get("field")).toString();
  42. row.createCell(column).setCellValue(value);
  43. column++;
  44. }
  45. }
  46. excelRow++;
  47. }
  48. }
  49. } catch (Exception e) {
  50. e.printStackTrace();
  51. }
  52. }



代码比较挫, 效率也低, 没办法, 因为需要按照指定的顺序生成. 也许有更好的办法, 我现在只是要按时完成需求.

这里就返回了想要的byte[].

最后一步就是在Response里返回流了.

  1. @RequestMapping(value = "/xxx")
  2. public void cell(HttpServletResponse response) throws Exception {
  3. byte[] bytes = cellService.selectExcel();
  4. response.setContentType("application/x-msdownload");
  5. response.setHeader("Content-Disposition", "attachment;filename=" + UUIDUtil.getUUID() + ".xls");
  6. response.setContentLength(bytes.length);
  7. response.getOutputStream().write(bytes);
  8. response.getOutputStream().flush();
  9. response.getOutputStream().close();
  10. }



这里注意的就是: 
response.setContentType("application/x-msdownload"); 
response.setHeader("Content-Disposition", "attachment;filename=" + UUIDUtil.getUUID() + ".xls");
一个是告诉浏览器需要下载, 下面一个就是告诉流程器下载是的文件名字. 这里我用的UUID. 

至此, 就完全OK了



    

转载于:https://my.oschina.net/vernon/blog/389039

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/842555
推荐阅读
相关标签
  

闽ICP备14008679号