文件上传,下载,预览,删除(File),分页接口(四)

简介: 文件上传,下载,预览,删除(File),分页接口

ExcelXlsxReader

package com.aostar.ida.framework.util.excel;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import com.aostar.ida.framework.base.exception.ServiceException;
/**
 * 处理大的excel表
 */
public class ExcelXlsxReader extends DefaultHandler {
    /**
     * 单元格中的数据可能的数据类型
     */
    enum CellDataType {
        BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
    }
    /**
     * 共享字符串表
     */
    private SharedStringsTable sst;
    /**
     * 上一次的索引值
     */
    private String lastIndex;
    /**
     * sheet名
     */
    private String sheetName = "";
    /**
     * 一行内cell集合
     */
    private List<CellVO> cellList = new ArrayList<>();
    /**
     * 判断整行是否为空行的标记
     */
    private boolean flag = false;
    /**
     * 当前行
     */
    private int curRow = 1;
    /**
     * 当前列
     */
    private int curCol = 0;
    /**
     * T元素标识
     */
    private boolean isTElement;
    /**
     * 单元格数据类型,默认为字符串类型
     */
    private CellDataType nextDataType = CellDataType.SSTINDEX;
    /**
     * 日期格式化
     */
    private final DataFormatter formatter = new DataFormatter();
    /**
     * 单元格日期格式的索引
     */
    private short formatIndex;
    /**
     * 日期格式字符串
     */
    private String formatString;
    /**
     * 定义前一个元素和当前元素的位置,用来计算其中空的单元格数量,如A6和A8等
     */
    private String preRef = null;
    /**
     * 当前元素位置
     */
    private String ref = null;
    /**
     * 定义该文档一行最大的单元格数,用来补全一行最后可能缺失的单元格
     */
    private String maxRef = null;
    /**
     * 单元格
     */
    private StylesTable stylesTable;
    /**
     * 当前sheet对象
     */
    private SheetVO curSheetVO;
    /**
     * 当前字段的数据类型
     */
    private int curDataType;
    /**
     * 遍历工作簿中所有的电子表格
     * 并缓存在mySheetList中
     *
     * @param bytes excel字节流
     * @throws IOException  异常
     * @throws OpenXML4JException  异常
     * @throws SAXException 异常
     * @return excel对象 
     */
    public ExcelVO process(byte[] bytes)
        throws IOException, OpenXML4JException, SAXException {
        InputStream inputStream = new ByteArrayInputStream(bytes);
        OPCPackage pkg = OPCPackage.open(inputStream);
        XSSFReader xssfReader = new XSSFReader(pkg);
        stylesTable = xssfReader.getStylesTable();
        SharedStringsTable sst = xssfReader.getSharedStringsTable();
        XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
        parser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        parser.setFeature("http://xml.org/sax/features/external-general-entities", false);
        parser.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        this.sst = sst;
        parser.setContentHandler(this);
        XSSFReader.SheetIterator sheets = (XSSFReader.SheetIterator)xssfReader.getSheetsData();
        ExcelVO excelVO = new ExcelVO();
        List<SheetVO> sheetList = new ArrayList<SheetVO>();
        excelVO.setSheets(sheetList);
        while (sheets.hasNext()) { // 遍历sheet
            curSheetVO = new SheetVO();
            List<RowVO> datas = new ArrayList<>();
            curSheetVO.setDatas(datas);
            curRow = 1; // 标记初始行为第一行
            InputStream sheet = sheets.next(); // sheets.next()和sheets.getSheetName()不能换位置,否则sheetName报错
            sheetName = sheets.getSheetName();
            curSheetVO.setName(sheetName);
            sheetList.add(curSheetVO);
            InputSource sheetSource = new InputSource(sheet);
            parser.parse(sheetSource); // 解析excel的每条记录,在这个过程中startElement()、characters()、endElement()这三个函数会依次执行
            sheet.close();
        }
        return excelVO; // 返回该excel文件的总行数,不包括首列和空行
    }
    /**
     * 第一个执行
     *
     */
    @Override
    public void startElement(String uri, String localName, String name, Attributes attributes)
        throws SAXException {
        // c => 单元格
        if ("c".equals(name)) {
          //开关位置不对,则证明转换后的xml只有c为没有v   <c r="XX" s="XX"></c>  这里需要自己补齐v的数据
          //由于计算实际V比较困难,这里采用有C就先占位,然后有V就替换列表最后一个元素的方式来处理
        CellVO cellVO = new CellVO();
            cellVO.setValue("");
            cellVO.setDataType(CellVO.DATA_TYPE_STRING);
            cellList.add(curCol, cellVO);
            curCol++ ;
            // 前一个单元格的位置
            if (preRef == null) {
                preRef = attributes.getValue("r");
            } else {
                preRef = ref;
            }
            // 当前单元格的位置
            ref = attributes.getValue("r");
            //检查是否有空单元格需要补齐
            int blankCount = countNullCell(ref, preRef);
            if(blankCount > 0){
              for (int i = 0; i < blankCount; i++ ) {
                CellVO blankVO = new CellVO();
                blankVO.setValue("");
                blankVO.setDataType(CellVO.DATA_TYPE_STRING);
                cellList.add(curCol, cellVO);
                curCol++ ;
              }
            }
            // 设定单元格类型
            this.setNextDataType(attributes);
        }
        // 当元素为t时
        if ("t".equals(name)) {
            isTElement = true;
        } else {
            isTElement = false;
        }
        // 置空
        lastIndex = "";
    }
    /**
     * 第二个执行
     * 得到单元格对应的索引值或是内容值
     * 如果单元格类型是字符串、INLINESTR、数字、日期,lastIndex则是索引值
     * 如果单元格类型是布尔值、错误、公式,lastIndex则是内容值
     */
    @Override
    public void characters(char[] ch, int start, int length)
        throws SAXException {
        lastIndex += new String(ch, start, length);
    }
    /**
     * 第三个执行
     *
     */
    @Override
    public void endElement(String uri, String localName, String name)
        throws SAXException {
        // t元素也包含字符串
        if (isTElement) {// 这个程序没经过
            // 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
            String value = lastIndex.trim();
            CellVO cellVO = new CellVO();
            cellVO.setValue(value);
            cellVO.setDataType(curDataType);
            cellList.set(curCol-1, cellVO);
            isTElement = false;
            // 如果里面某个单元格含有值,则标识该行不为空行
            if (value != null && !"".equals(value)) {
                flag = true;
            }
        } else if ("v".equals(name)) {
            // v => 单元格的值,如果单元格是字符串,则v标签的值为该字符串在SST中的索引
            String value = this.getDataValue(lastIndex.trim(), "");// 根据索引值获取对应的单元格值
            if(null != value){
              value = value.trim();
            }
            CellVO cellVO = new CellVO();
            cellVO.setValue(value);
            cellVO.setDataType(curDataType);
            cellList.set(curCol-1, cellVO);
            // 如果里面某个单元格含有值,则标识该行不为空行
            if (value != null && !"".equals(value)) {
                flag = true;
            }
        } else {
            // 如果标签名称为row,这说明已到行尾,调用optRows()方法
            if ("row".equals(name)) {
                // 默认第一行为表头,以该行单元格数目为最大数目
                if (curRow == 1) {
                    maxRef = ref;
                    // 表头
                    List<String> titles = new ArrayList<>();
                    for (CellVO cell : cellList) {
                        String titleStr = cell.getValue().trim();
                        // 处理特殊字符,全部替换为下划线,避免SQL报错,只保留汉字,字母,数字
                        String patten = "[^\u4e00-\u9fa5a-zA-Z0-9]";
                        titleStr = titleStr.replaceAll(patten, "_");
                        if (StringUtils.isBlank(titleStr)) {
                            throw new ServiceException("表格的第一行必须有值");
                        }
                        // 处理表头过长
                        if (titleStr.length() > 40) {
                            titleStr = titleStr.substring(0, 40);
                        }
                        titles.add(titleStr);
                    }
                    curSheetVO.setTitles(titles);
                }
                // 补全一行尾部可能缺失的单元格
                if (maxRef != null) {
                  //检查是否有空单元格需要补齐
                    int blankCount = countNullCell(maxRef, ref);
                    if(blankCount >= 0){
                      for (int i = 0; i <= blankCount; i++ ) {
                        CellVO blankVO = new CellVO();
                        blankVO.setValue("");
                        blankVO.setDataType(CellVO.DATA_TYPE_STRING);
                        cellList.add(curCol, blankVO);
                        curCol++ ;
                      }
                    }
                }
                if (flag && curRow != 1) { // 该行不为空行且该行不是第一行,则发送(第一行为列名,不需要)
                    List<RowVO> datas = curSheetVO.getDatas();
                    RowVO rowVO = new RowVO();
                    datas.add(rowVO);
                    List<CellVO> cells = new ArrayList<>();
                    rowVO.setCells(cells);
                    for (CellVO cell : cellList) {
                        CellVO cellVO = new CellVO();
                        String value = cell.getValue();
                        if(null != value){
                          value = value.trim();
                        }
                        cellVO.setValue(value);
                        cellVO.setDataType(cell.getDataType());
                        cells.add(cellVO);
                    }
                }
                cellList.clear();
                curRow++ ;
                curCol = 0;
                preRef = null;
                ref = null;
                flag = false;
            }
        }
    }
    /**
     * 处理数据类型
     *
     * @param attributes 属性
     */
    public void setNextDataType(Attributes attributes) {
        nextDataType = CellDataType.NUMBER; // cellType为空,则表示该单元格类型为数字
        formatIndex = -1;
        formatString = null;
        String cellType = attributes.getValue("t"); // 单元格类型
        String cellStyleStr = attributes.getValue("s"); //
        if ("b".equals(cellType)) { // 处理布尔值
            nextDataType = CellDataType.BOOL;
        } else if ("e".equals(cellType)) { // 处理错误
            nextDataType = CellDataType.ERROR;
        } else if ("inlineStr".equals(cellType)) {
            nextDataType = CellDataType.INLINESTR;
        } else if ("s".equals(cellType)) { // 处理字符串
            nextDataType = CellDataType.SSTINDEX;
        } else if ("str".equals(cellType)) {
            nextDataType = CellDataType.FORMULA;
        }
        if (cellStyleStr != null) { // 处理日期
            int styleIndex = Integer.parseInt(cellStyleStr);
            XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
            formatIndex = style.getDataFormat();
            formatString = style.getDataFormatString();
            if (formatString.contains("m/d/yy")) {
                nextDataType = CellDataType.DATE;
                formatString = "yyyy-MM-dd hh:mm:ss";
            }
            if (formatString == null) {
                nextDataType = CellDataType.NULL;
                formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
            }
        }
    }
    /**
     * 对解析出来的数据进行类型处理
     * @param value   单元格的值,
     *                value代表解析:BOOL的为0或1, ERROR的为内容值,FORMULA的为内容值,INLINESTR的为索引值需转换为内容值,
     *                SSTINDEX的为索引值需转换为内容值, NUMBER为内容值,DATE为内容值
     * @param thisStr 一个空字符串
     * @return 单元格的值
     */
    public String getDataValue(String value, String thisStr) {
        curDataType = CellVO.DATA_TYPE_STRING;
        switch (nextDataType) {
            // 这几个的顺序不能随便交换,交换了很可能会导致数据错误
            case BOOL: // 布尔值
                char first = value.charAt(0);
                thisStr = first == '0' ? "FALSE" : "TRUE";
                break;
            case ERROR: // 错误
                thisStr = "\"ERROR:" + value.toString() + '"';
                break;
            case FORMULA: // 公式
                thisStr = '"' + value.toString() + '"';
                break;
            case INLINESTR:
                XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
                thisStr = rtsi.toString();
                rtsi = null;
                break;
            case SSTINDEX: // 字符串
                String sstIndex = value.toString();
                try {
                    int idx = Integer.parseInt(sstIndex);
                    XSSFRichTextString rtss = new XSSFRichTextString(sst.getEntryAt(idx));// 根据idx索引值获取内容值
                    thisStr = rtss.toString();
                    rtss = null;
                } catch (NumberFormatException ex) {
                    thisStr = value.toString();
                }
                break;
            case NUMBER: // 数字
                curDataType = CellVO.DATA_TYPE_NUMERIC;
                if (formatString != null) {
                    thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString).trim();
                } else {
                    thisStr = value;
                }
                thisStr = thisStr.replace("_", "").trim();
                break;
            case DATE: // 日期
                curDataType = CellVO.DATA_TYPE_DATE;
                thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString);
                // 对日期字符串作特殊处理,去掉T
                thisStr = thisStr.replace("T", " ");
                break;
            default:
                thisStr = " ";
                break;
        }
        return thisStr;
    }
    private int countNullCell(String ref, String preRef) {
        // excel2007最大行数是1048576,最大列数是16384,最后一列列名是XFD
        String xfd = ref.replaceAll("\\d+", "");
        String preXfd = preRef.replaceAll("\\d+", "");
        xfd = fillChar(xfd, 3, '@', true);
        preXfd = fillChar(preXfd, 3, '@', true);
        char[] letter = xfd.toCharArray();
        char[] preLetter = preXfd.toCharArray();
        int res = (letter[0] - preLetter[0]) * 26 * 26 + (letter[1] - preLetter[1]) * 26 + (letter[2] - preLetter[2]);
        return res - 1;
    }
    private String fillChar(String str, int len, char let, boolean isPre) {
        int strLen = str.length();
        if (strLen < len) {
            if (isPre) {
                for (int i = 0; i < (len - strLen); i++ ) {
                    str = let + str;
                }
            } else {
                for (int i = 0; i < (len - strLen); i++ ) {
                    str = str + let;
                }
            }
        }
        return str;
    }
}

SheetVO

/*
 * 文件名:SheetVO.java
 * 版权:Copyright by aostarit
 * 描述:sheet实体
 */
package com.aostar.ida.framework.util.excel;
import java.util.List;
/**
 * excel的sheet实体对象
 * 
 * @version 2019年5月17日
 */
public class SheetVO {
    /**
     * 名称
     */
    private String name;
    /**
     * 表头列表--暂时只支持单表头,不支持跨行--约定为第一行
     */
    private List<String> titles;
    /**
     * 数据内容--不含表头
     */
    private List<RowVO> datas;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<String> getTitles() {
        return titles;
    }
    public void setTitles(List<String> titles) {
        this.titles = titles;
    }
    public List<RowVO> getDatas() {
        return datas;
    }
    public void setDatas(List<RowVO> datas) {
        this.datas = datas;
    }
}

RowVO

/*
 * 文件名:RowVO.java
 * 版权:Copyright by aostarit
 * 描述:excel行
 */
package com.aostar.ida.framework.util.excel;
import java.util.List;
/**
 * excel行对象
 * 
 * @version 2019年5月17日
 */
public class RowVO {
    /**
     * 单元格数据
     */
    private List<CellVO> cells;
    public List<CellVO> getCells() {
        return cells;
    }
    public void setCells(List<CellVO> cells) {
        this.cells = cells;
    }
}

CellVO

/*
 * 文件名:CellVO.java
 * 版权:Copyright by aostarit
 * 描述:单元格对象
 */
package com.aostar.ida.framework.util.excel;
/**
 * 单元格实体
 * 
 * @version 2019年5月17日
 */
public class CellVO {
    /**
     * 数字类型
     */
    public static final int DATA_TYPE_NUMERIC = 1;
    /**
     * 字符串类型
     */
    public static final int DATA_TYPE_STRING = 2;
    /**
     * 日期类型
     */
    public static final int DATA_TYPE_DATE = 3;
    /**
     * 单元格的值
     */
    private String value;
    /**
     * 值的类型
     */
    private int dataType;
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public int getDataType() {
        return dataType;
    }
    public void setDataType(int dataType) {
        this.dataType = dataType;
    }
}

控制台

@Override
  public MsgContext exportSheetDatas(HttpServletResponse response,Long sheetId, int currentPageNo, int pageSize) {
    BizIdxSheets sheetPO = idxSheetsMapper.selectByPrimaryKey(Sutil.checkData(StringUtils.EMPTY, sheetId));
    if (null == sheetPO) {
      throw new ServiceException("未找到该指标图层信息!");
    }
    IdxSqlHander idxSqlHander = SpringUtil.getBean("idxSqlHander", IdxSqlHander.class);
    Map<String, Object> allMap=idxSqlHander.init(sheetId).queryData(currentPageNo, pageSize);
    List<Map> list = (List<Map>) allMap.get("titles");
    for (Map map : list) {
      map.get("label");
      LOGGER.info("===map=>"+map.get("label"));
    }
//    List<Map> listss1 = (List<Map>) allMap.get("datas");
//    
//    LOGGER.info("===listss=>"+listss1);
//    
//    listss1.forEach(li->{
//      li.values().forEach(v->{
//        LOGGER.info("=88=>"+v);
//      });
//      li.keySet().forEach(k->{
//        LOGGER.info("=99=>"+k);
//      });
//    });
  //  ArrayList<Map<String, Object>> rows = (ArrayList<Map<String, Object>>)allMap.get("datas");
  //  List<Map<String, Object>> compDatas = (List<Map<String, Object>>)allMap.get("datas");
    List<Map<String, String>> compTitles = (List<Map<String, String>>)MapUtils.getObject(allMap, "titles");
    List<Map<String, Object>> compDatas = (List<Map<String, Object>>)MapUtils.getObject(allMap, "datas");
    LOGGER.info("===compDatas=2>"+compDatas);
    LOGGER.info("===compTitles=2>"+compTitles);
     List<String> titles = new ArrayList<String>();
     for(Map<String, String> map : compTitles){
        titles.add(MapUtils.getString(map, "label"));
      }
      LOGGER.info("===titles=2>"+titles);
     List<List<Object>> exportDatas = new ArrayList<List<Object>>(compDatas.size());
     LOGGER.info("===exportDatas.size()==》"+exportDatas.size());
      for (int i = 0; i < compDatas.size(); i++ ) {
              List<Object> rowData = new ArrayList<Object>();
              Map<String, Object> compData = compDatas.get(i);
              for(String title : titles){
                rowData.add(MapUtils.getString(compData, title, ""));                
              }
              exportDatas.add(rowData);
          }
     LOGGER.info("===exportDatas=2>"+exportDatas);
    LOGGER.info("===json=2>"+JSON.toJSONString(allMap.get("titles")));
//    JSONArray  ac=JSON.parseArray(JSON.toJSONString(allMap.get("titles")));
//        
//    LOGGER.info("===ac=2>"+ac);
//    
//    
//    
//     for (int i = 0; i < ac.size(); i++) {
//       Map<String, Object> map = (Map<String, Object>) ac.get(i);
//       Iterator iterator = map.keySet().iterator();
//              while (iterator.hasNext()) {
//                  String string = (String) iterator.next();                
//                  LOGGER.info("===map.get(string)>"+map.get(string));
//              }
//
//     }
//     
//     JSONArray  ab=JSON.parseArray(JSON.toJSONString(allMap.get("datas")));
//        
//  
//     for (int i = 0; i < ab.size(); i++) {
//       Map<String, Object> map = (Map<String, Object>) ac.get(i);
//       Iterator iterator = map.keySet().iterator();
//              while (iterator.hasNext()) {
//                  String string = (String) iterator.next();                
//                  LOGGER.info("===map.get(string)>"+map.get(string));
//              }
//
//     }
//    
    HSSFWorkbook book=  ExcelUtils.data2Excel(exportDatas, titles, "sheet");
  //  String sceName = MapUtils.getString(allMap, "sceName");
    String sceName = "ExportXls";
      OutputStream os = null;
    try {
      os = response.getOutputStream();
      response.reset();// 清空输出流
      response.setContentType("application/x-msdownload");
      response.setCharacterEncoding("utf-8");
      response.setContentType("text/html;charset=utf-8");
      response.setHeader("Content-disposition", "attachment; filename="+URLEncoder.encode(sceName, "UTF-8")+".xls");// 设定输出文件头
      response.setContentType("application/msexcel");// 定义输出类型
      book.write(os);
      LOGGER.info("导出完成关闭流");
    } catch (IOException e) {
      return MsgContext.createErrorContext("导出失败。");
    } finally {
      IOUtils.closeQuietly(os);
    }
       return null;   
  }

allMap 数据类型为

allMap==>{sortColName=, datas=[{number=100, name=电工, deptID=200, ID=1}, {number=150, name=水工, deptID=300, ID=2}, {number=200, name=领导, deptID=400, ID=3}, {number=5000, name=董事长, deptID=250, ID=4}], titles=[{sign=, label=number, type=1}, {sign=, label=name, type=1}, {sign=, label=deptID, type=2}, {sign=, label=ID, type=2}], totalCount=4}
相关文章
|
18天前
|
API
【sgUpload】自定义组件:自定义上传组件,支持上传文件夹及其子文件夹文件、批量上传,批量上传会有右下角上传托盘出现,支持本地上传图片转换为Base64image。
【sgUpload】自定义组件:自定义上传组件,支持上传文件夹及其子文件夹文件、批量上传,批量上传会有右下角上传托盘出现,支持本地上传图片转换为Base64image。
|
4月前
ant-design Upload上传组件使用 编辑功能图片回显
ant-design Upload上传组件使用 编辑功能图片回显
167 0
|
8月前
针对FastAdmin新增上传多个图片,新增上传的视频的预览效果
针对FastAdmin新增上传多个图片,新增上传的视频的预览效果
388 0
|
9月前
文件上传,下载,预览,删除(File),分页接口(三)
文件上传,下载,预览,删除(File),分页接口
36 0
|
9月前
|
存储
Photoshop合并多个图片为PDF格式文件的(PDF文件编辑删除页面及合并的操作方法)解决方案
Photoshop合并多个图片为PDF格式文件的(PDF文件编辑删除页面及合并的操作方法)解决方案
194 0
|
4月前
|
小程序 应用服务中间件 Shell
laravel8(三)文件上传提示 “The file deos not exits ” ,但确实已经上传了文件
Laravel 文件上传提示 “The file "" deos not exits ” ,但确实已经上传了文件
36 1
|
9月前
|
JavaScript Java
文件上传,下载,预览,删除(File),分页接口(二)
文件上传,下载,预览,删除(File),分页接口
135 0
|
9月前
|
XML Java 数据库
文件上传,下载,预览,删除(File),分页接口(一)
文件上传,下载,预览,删除(File),分页接口
52 0
|
9月前
|
存储 Java
Java实现文件上传到本地(自定义保存路径)
Java实现文件上传到本地(自定义保存路径)
611 0
|
9月前
|
安全 前端开发
fastadmin自定义excel文件导入,实现文件上传功能 --已实现
fastadmin自定义excel文件导入,实现文件上传功能 --已实现
527 0