package com.nis.util.excel; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Lists; import com.nis.domain.basics.ServiceDictInfo; import com.nis.util.DictUtils; import com.nis.util.Encodes; import com.nis.util.Reflections; import com.nis.util.StringUtil; public class ExcelCsv { private static Logger log = LoggerFactory.getLogger(ExcelCsv.class); private static BufferedWriter cs; /**解决乱码问题 * @see http://www.cnblogs.com/tangkai/p/3818084.html */ private final static byte bom[] = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }; private final static String charset = "UTF-8"; /** * 注解列表(Object[]{ ExcelField, Field/Method }) */ List annotationList = Lists.newArrayList(); static Map> annotationMap=new HashMap<>(); /** * //递归获取cls实体对象及父级对象的method * @param list * @param cls */ public static void getMethods(List list,Class cls) { Method[] methods=cls.getDeclaredMethods(); if(methods != null && methods.length > 0){ List tempList=new ArrayList<>(); for (Method method : methods) { if(list.size()==0) { tempList.add(method); }else { boolean has=false; for(Method checkM:list) { if(checkM.getName().equals(method.getName())) { has=true; break; } } if(!has) { tempList.add(method); } } } list.addAll(tempList); } if(cls.getSuperclass() != null){ getMethods(list,cls.getSuperclass()); } } /** * //递归获取cls实体对象及父级对象的属性 * wx:修改,子类覆盖父类的同名方法 * @param list * @param cls */ public static void getFields(List list,Class cls) { Field[] fields=cls.getDeclaredFields(); if(fields != null && fields.length > 0){ List tempList=new ArrayList<>(); for (Field field : fields) { if(list.size()==0) { tempList.add(field); }else { boolean has=false; for(Field checkF:list) { if(checkF.getName().equals(field.getName())) { has=true; break; } } if(!has) { tempList.add(field); } } } list.addAll(tempList); } if(cls.getSuperclass() != null){ getFields(list,cls.getSuperclass()); } } /** * 构造函数 * @param msgProp 国际化配置 * @param title sheet名称 * @param cls 实体对象,通过annotation.ExportField获取标题 * @param type 导出类型(1:导出数据;2:导出模板) * @param groups 导入分组 * @return */ public static Map> ExcelCsvHeader(Properties msgProp,List titleList,Map noExportMap,Map> clsMap, int type, int... groups){ Map> headerMap=new HashMap>(); Map> commentMap=new HashMap>(); for (String title : titleList) { String noExportField=noExportMap.get(title); noExportField=",do_blacklist,"+noExportField; List annotationList = Lists.newArrayList(); List list=new ArrayList(); // Get annotation field //递归获取cls实体对象及父级对象的属性 getFields(list, clsMap.get(title)); if(!StringUtil.isEmpty(list)){ for (Field f : list){ ExcelField ef = f.getAnnotation(ExcelField.class); if (ef != null && (ef.type()==0 || ef.type()==type)){ if (groups!=null && groups.length>0){ boolean inGroup = false; for (int g : groups){ if (inGroup){ break; } for (int efg : ef.groups()){ if (g == efg){ inGroup = true; if(!StringUtil.isEmpty(ef.title()) && !(noExportField.indexOf(","+ef.title()+",") > -1)){ annotationList.add(new Object[]{ef, f}); } break; } } } }else{ if(!StringUtil.isEmpty(ef.title()) && !(noExportField.indexOf(","+ef.title()+",") > -1)){ annotationList.add(new Object[]{ef, f}); } } } } } List ms=new ArrayList(); // Get annotation method //递归获取cls实体对象及父级对象的属性 getMethods(ms, clsMap.get(title)); if(!StringUtil.isEmpty(ms)){ for (Method m : ms){ ExcelField ef = m.getAnnotation(ExcelField.class); if (ef != null && (ef.type()==0 || ef.type()==type)){ if (groups!=null && groups.length>0){ boolean inGroup = false; for (int g : groups){ if (inGroup){ break; } for (int efg : ef.groups()){ if (g == efg){ inGroup = true; if(!StringUtil.isEmpty(ef.title()) && !(noExportField.indexOf(","+ef.title()+",") > -1)){ annotationList.add(new Object[]{ef, m}); } break; } } } }else{ if(!StringUtil.isEmpty(ef.title()) && !(noExportField.indexOf(","+ef.title()+",") > -1)){ annotationList.add(new Object[]{ef, m}); } } } } } // Field sorting Collections.sort(annotationList, new Comparator() { public int compare(Object[] o1, Object[] o2) { return new Integer(((ExcelField)o1[0]).sort()).compareTo( new Integer(((ExcelField)o2[0]).sort())); }; }); // Initialize List headerList = Lists.newArrayList(); List commentList = Lists.newArrayList(); for (Object[] os : annotationList){ String titleStr = ((ExcelField)os[0]).title(); String commentStr = ((ExcelField)os[0]).comment(); // 如果是导出,则去掉注释 if (type==1){ commentStr=""; } if(!StringUtil.isEmpty(titleStr)){ //去掉不需要展示的header //去掉不需要展示的header String noExport=""; if(noExportField.contains("&")){ noExport=noExportField.substring(0,noExportField.indexOf("&")); }else{ noExport=noExportField; } if(!(noExport.indexOf(","+titleStr+",") > -1)){ //需要替换的header boolean flag=true; if(noExportField.contains("&")){ String replaceField=noExportField.substring(noExportField.indexOf("&")+1); String[] replaceStr=replaceField.split("-"); for (int i = 0; i < replaceStr.length; i++) { String [] fields=replaceStr[i].split(":"); if(fields[0].equals(titleStr)){ titleStr=msgProp.getProperty(fields[1],fields[1]); flag=false; break; } } } if(flag){ titleStr=msgProp.getProperty(titleStr)==null?titleStr:msgProp.getProperty(titleStr,titleStr); } headerList.add(titleStr); commentList.add(commentStr); } } } headerMap.put(title, headerList); commentMap.put(title, commentList); annotationMap.put(title, annotationList); } return headerMap; } /** * 添加数据(通过annotation.ExportField添加数据) * @param * @return list 数据列表 */ public static Map>> setDataList(Properties msgProp, Map dataMap, Map map){ Map>> dataList=new HashMap>>(); Set keyList=dataMap.keySet(); for (String key : keyList) { List list=dataMap.get(key); List> listT=new ArrayList>(); for (E e : list){ int colunm = 0; List lisb=new ArrayList(); for (Object[] os : annotationMap.get(key)){ ExcelField ef = (ExcelField)os[0]; Object val = null; // Get entity value try{ if (StringUtils.isNotBlank(ef.value())){ val = Reflections.invokeGetter(e, ef.value()); }else{ if (os[1] instanceof Field){ val = Reflections.invokeGetter(e, ((Field)os[1]).getName()); }else if (os[1] instanceof Method){ val = Reflections.invokeMethod(e, ((Method)os[1]).getName(), new Class[] {}, new Object[] {}); } } // If is dict, get dict label String valStr=val==null?"":val.toString(); if (StringUtils.isNotBlank(ef.dictType())){ if("type".equals(ef.dictType()) || "attribute".equals(ef.dictType()) || "label".equals(ef.dictType())){ // Get basic info val = getBasicInfo(ef.dictType(),map,valStr); }else{ //字典数据已做国际化处理 String dict=DictUtils.getDictLabel(ef.dictType(), valStr, valStr); //如果找不到字典国际化值,把字典本身作为默认值放进去,不然导出就是空了 val = msgProp.getProperty(dict,dict); //业务配置-stream 阻断类型中 阻断 改为 封堵(丢弃) if("block_type".equals(ef.title()) && dict.equals("action_reject") && (Reflections.invokeGetter(e, "serviceId").toString().equals("35") || Reflections.invokeGetter(e, "serviceId").toString().equals("33") || Reflections.invokeGetter(e, "serviceId").toString().equals("36"))){ dict="block_drop"; val = msgProp.getProperty(dict,dict); } //ip spoofing redirect动作修改为Spoofing if(ef.title().equals("block_type") && (Reflections.invokeGetter(e, "serviceId").toString().equals("518"))) { dict="action_spoofing"; val = msgProp.getProperty(dict,dict); } } } if(ef.title().equals("whether_area_block")&&!StringUtil.isEmpty(val)){ Integer whetherAreaBlock=Integer.parseInt(valStr); if(whetherAreaBlock.equals(0)){ val = msgProp.getProperty("all","all"); }else if(whetherAreaBlock.equals(1)){ val = msgProp.getProperty("selective","selective"); }else{ val =""; } } if(ef.title().equals("is_hex") && !StringUtil.isEmpty(val)){ Integer isHex=Integer.parseInt(val.toString()); if(isHex.equals(0) || isHex.equals(2)){ val = msgProp.getProperty("not_hex","not_hex"); }else if(isHex.equals(1)){ val = msgProp.getProperty("hex","hex"); }else{ val =""; } } if(ef.title().equals("is_case_insenstive") && !StringUtil.isEmpty(val)){ Integer isCaseSenstive=Integer.parseInt(val.toString()); if(isCaseSenstive.equals(0)){ val = msgProp.getProperty("case_insenstive","case_insenstive"); }else if(isCaseSenstive.equals(1)){ val = msgProp.getProperty("case_senstive","case_senstive"); }else{ val =""; } } if(!StringUtil.isEmpty(val)) { if (val instanceof Date){ SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); val=sdf.format(val); } } }catch(Exception ex) { log.error("Get entity value failed",ex); val = ""; } lisb.add(String.valueOf(val)); } listT.add(lisb); //listT.add(String.valueOf(sb)); } dataList.put(key, listT); } return dataList; } public static void writeCSVFile(HttpServletResponse response,List titleList,Map> headMap, Map>> dataMap,String fileName, String titleTime,Properties msgProp) { try { // 写入临时文件 File tempFile = File.createTempFile("vehicle", ".csv"); cs = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile), "utf-8"), 1024); cs.write(new String(bom, charset)); //获取头部数据 for (int i = 0; i < titleList.size(); i++) { if(i==0){ //写入时间范围 if(!StringUtils.isEmpty(titleTime)){ cs.write(titleTime); cs.newLine(); } } List heads=headMap.get(titleList.get(i)); if(i>0){ //写入域配置标题 cs.newLine(); if(!StringUtils.isEmpty(titleList.get(i))){ cs.write(msgProp.getProperty(titleList.get(i), titleList.get(i))); cs.newLine(); } } // 写入文件头部 writeHead(heads, cs); //获取文件内容 List> datas=dataMap.get(titleList.get(i)); // 写入文件内容 for (List row: datas) { writeRow(row, cs); } } cs.flush(); OutputStream out = response.getOutputStream(); byte[] b = new byte[10240]; File fileLoad = new File(tempFile.getCanonicalPath()); response.reset(); response.setContentType("application/octet-stream; charset=utf-8"); response.setHeader("Content-Disposition", "attachment; filename="+fileName); long fileLength = fileLoad.length(); String length1 = String.valueOf(fileLength); response.setHeader("Content_Length", length1); FileInputStream in = new FileInputStream(fileLoad); int n; while ((n = in.read(b)) != -1) { out.write(b, 0, n); // 每次写入out1024字节 } in.close(); out.close(); deleteFile(tempFile); } catch (Exception e) { e.printStackTrace(); } } public static boolean deleteFile( File file) { // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除 if (file.exists() && file.isFile()) { if (file.delete()) { return true; } else { return false; } } else { return false; } } private static void writeHead(List titles, BufferedWriter csvWriter) throws IOException { // 写入文件头部 for (String title : titles) { StringBuffer sb = new StringBuffer(); if(isDate(title)){ title=title + "\t"; } String rowStr = sb.append("\"").append(title).append("\",").toString(); csvWriter.write(rowStr); } csvWriter.newLine(); } private static void writeRow(List data, BufferedWriter csvWriter) throws Exception { // 写入文件内容 //Html 解码 for (String tag : data) { tag = Encodes.unescapeHtml(tag.toString()); StringBuffer sb = new StringBuffer(); if("null".equals(tag.trim())){ tag=null; } if(StringUtils.isNotBlank(tag)){ // 替换值中双引号 if(tag.contains("\"")){ tag = tag.replace("\"", ""); } // \t解决数字0开头字符串,0显示不出来的问题,比如邮编 /*if(tag.startsWith("0") && !tag.contains(".")){ tag = tag + "\t"; }*/ if(isDate(tag)){ tag=tag + "\t"; } } String rowStr = sb.append("\"").append(tag==null?"":tag).append("\",").toString(); csvWriter.write(rowStr); } csvWriter.newLine(); } /** * 设置性质、分类、标签等信息 * @param dictType * @param map * @param val * @return */ public static String getBasicInfo(String dictType,Map map,String val) { String basicInfo=""; List list=new ArrayList(); if("type".equals(dictType)){ list=(List) map.get("fls"); for (String info : val.split(",")) { for (ServiceDictInfo dictInfo : list) { if(info.equals(dictInfo.getServiceDictId().toString())){ basicInfo+=","+dictInfo.getItemValue(); } } } } if("attribute".equals(dictType)){ list=(List) map.get("xzs"); for (String info : val.split(",")) { for (ServiceDictInfo dictInfo : list) { if(info.equals(dictInfo.getServiceDictId().toString())){ basicInfo+=","+dictInfo.getItemValue(); } } } } if("label".equals(dictType)){ list=(List) map.get("labels"); for (String info : val.split(",")) { for (ServiceDictInfo dictInfo : list) { if(info.equals(dictInfo.getServiceDictId().toString())){ basicInfo+=","+dictInfo.getItemValue(); } } } } if(!StringUtil.isEmpty(basicInfo)){ basicInfo=basicInfo.substring(1); } return basicInfo; } /** * 功能:判断字符串是否为日期格式 * * @param str * @return */ public static boolean isDate(String strDate) { Pattern pattern = Pattern .compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$"); boolean flag=false; if(strDate.trim().length()>=10){ strDate=strDate.trim().substring(0, 10); Matcher m = pattern.matcher(strDate); if (m.matches()) { return true; } else { return false; } }else{ if(strDate.trim().length()==7){ pattern = Pattern.compile("^\\d{4}-\\d{2}$"); Matcher m = pattern.matcher(strDate); if (m.matches()) { return true; } else { return false; } }else{ return false; } } } public static void ajaxCSVFile(HttpServletResponse response,ListtitleList,List>dataMap,String fileName, String titleTime,Properties msgProp) { try { // 写入临时文件 File tempFile = File.createTempFile("vehicle", ".csv"); cs = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile), "utf-8"), 1024); cs.write(new String(bom, charset)); //写入时间范围 if(!StringUtils.isEmpty(titleTime)){ cs.write(titleTime); cs.newLine(); } // 写入文件头部 writeHead(titleList, cs); // 写入文件内容 for (List row: dataMap) { writeRow(row, cs); } cs.flush(); OutputStream out = response.getOutputStream(); byte[] b = new byte[10240]; File fileLoad = new File(tempFile.getCanonicalPath()); response.reset(); response.setContentType("application/octet-stream; charset=utf-8"); response.setHeader("Content-Disposition", "attachment; filename="+fileName); long fileLength = fileLoad.length(); String length1 = String.valueOf(fileLength); response.setHeader("Content_Length", length1); FileInputStream in = new FileInputStream(fileLoad); int n; while ((n = in.read(b)) != -1) { out.write(b, 0, n); // 每次写入out1024字节 } in.close(); out.close(); deleteFile(tempFile); } catch (Exception e) { e.printStackTrace(); } } }