package com.zcloud.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFPatriarch; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.Entry; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.lang.reflect.Method; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.*; public class ImageExcelUtil { private static final Log log = LogFactory.getLog(ImageExcelUtil.class); /** * excel工具类,可导出带图片或不带图片的数据 * * @param titles 第一行的标题列 * @param rows 数据行量 * @param maps 装载导出数据的封装了map的list数据集合,注意:此中的map尽量用本类中的方法 javaBean2Map直接生成,或自己拼接;但需与参数titles[]的标题相关数据对应上 * @param fileName 导出到本地的文件路径和文件名 * @param response response * @param path 保存到本地的图片地址(我这里是为了删除该目录下的图片,因为我是把网络图片保存到到本地的,如果图片已经是本地图片的话就不需要删除) * @date 2024/03/20 */ public static void excelOut(String[] titles, int rows, List> maps, String fileName, HttpServletResponse response, String path) { OutputStream out = null; BufferedImage bufferImg = null; HSSFWorkbook wb = null; try { //创建工作sheet wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(fileName); //设置单元格内容水平垂直居中 HSSFCellStyle style = wb.createCellStyle(); // style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // style.setAlignment(HSSFCellStyle.ALIGN_CENTER); style.setWrapText(true); //设置内容自动换行 //画图的顶级管理器,一个sheet只能获取一个(一定要注意这点) HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); HSSFRow row0 = sheet.createRow(0); row0.setHeightInPoints(25); if (titles.length == 0) { return; } HSSFCell cell = null; //第一行、标题行列 for (int i = 0; i < titles.length; i++) { cell = row0.createCell(i); //第一个单元格 cell.setCellValue(titles[i]); //设定值 cell.setCellStyle(style); sheet.setColumnWidth(i, 6000); } HSSFRow row = null; HSSFCell cellRow = null; HSSFClientAnchor anchor = null; for (int i = 1; i <= rows; i++) { int cellColumn = 0; //创建行 row = sheet.createRow(i); //设置默认行高 row.setHeightInPoints(15); //行数据处理 Map stringObjectMap = maps.get(i - 1); for (Object value : stringObjectMap.keySet()) { //行单元格 cellRow = row.createCell(cellColumn); cellRow.setCellStyle(style); //如果行数据中有图片时候的处理 if ("USER_SIGN_FILE".equals(value) || "PORTRAIT".equals(value)) { File file = (File) stringObjectMap.get(value); if (file == null) { cellRow.setCellValue(""); continue; } else { row.setHeightInPoints(50); ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); cellRow = row.createCell(cellColumn); cellRow.setCellStyle(style); sheet.setColumnWidth(cellColumn, 5000); log.error("图片路径" + file); bufferImg = ImageIO.read(file); ImageIO.write(bufferImg, "jpg", byteArrayOut); anchor = new HSSFClientAnchor(0, 0, 1023, 255, (short) cellColumn, i, (short) cellColumn, i); patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG)); cellColumn++; } } if (stringObjectMap.get(value) != null) { cellRow.setCellValue(stringObjectMap.get(value).toString()); } else { cellRow.setCellValue(""); } cellColumn++; } } if (wb != null) { out = response.getOutputStream(); response.setContentType("application/x-msdownload"); response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xls"); // 写入excel文件 wb.write(out); } } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { try { out.close(); //执行删除生成的图片 TODO // File file = new File("E:\\data\\nginxd\\sportsApplets");//输入要删除文件目录的绝对路径 // File file = new File("/data/nginxd/sportsApplets/excelDeleteImage/");//输入要删除文件目录的绝对路径 File file = new File(path);//输入要删除文件目录的绝对路径 deleteFile(file);//由于是保存网络图片到本地服务区,所以画完图片到excel就要删除文件 } catch (IOException e) { e.printStackTrace(); } } } } /** * 删除文件夹目录下的所有文件 (我是怕到时候本地服务器图片越来越多,占用资源,所以把图片洗完到excel里面就删除) * * @param file * @date 2021/01/11 */ public static void deleteFile(File file) { //判断文件不为null或文件目录存在 if (file == null || !file.exists()) { log.error("文件删除失败,请检查文件路径是否正确"); return; } //取得这个目录下的所有子文件对象 File[] files = file.listFiles(); //遍历该目录下的文件对象 for (File f : files) { //打印文件名 String name = file.getName(); log.error("删除的文件名" + name); //判断子目录是否存在子目录,如果是文件则删除 if (f.isDirectory()) { deleteFile(f); } else { f.delete(); } } //删除空文件夹 for循环已经把上一层节点的目录清空。 file.delete(); } /** * 保存图片到本地 * * @param imageUrl * @param path * @return * @date 2021/01/11 */ public static String saveFile(String imageUrl, String path) { String filename = imageUrl.substring(imageUrl.lastIndexOf("/") + 1, imageUrl.length()); log.error("图片====" + filename); // Random rand = new Random(); // int s = rand.nextInt(900)+ 100; int s = (int) (Math.random() * 10000); log.error("随机数==" + s); filename = s + filename; //这里如果有文件名称重复的,就取一个随机数拼接文件名 File sf = null; OutputStream os = null; InputStream is = null; try { // 构造URL URL url = new URL(imageUrl); // 打开连接 URLConnection con = url.openConnection(); //设置请求超时为5s con.setConnectTimeout(5 * 1000); // 输入流 is = con.getInputStream(); // 1K的数据缓冲 byte[] bs = new byte[1024]; // 读取到的数据长度 int len; // 输出的文件流 // String path = "E:\\data\\nginxd\\sportsApplets"; // String path = "/data/nginxd/sportsApplets/excelDeleteImage/"; sf = new File(path); if (!sf.exists()) { sf.mkdirs(); } os = new FileOutputStream(sf.getPath() + "/" + filename); // 开始读取 while ((len = is.read(bs)) != -1) { os.write(bs, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { // 完毕,关闭所有链接 try { if (os != null) { os.close(); } if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } } return sf.getPath() + "/" + filename; } /** * 将java类对象属性-值转换成map的键值对 去除getClass方法属性,以及自定义的file属性放置最后。 * * @param javaBean * @return Map * @throws Exception * @date 2021/01/11 */ public static Map javaBean2Map(Object javaBean) throws Exception { Map map = new LinkedHashMap<>(); //反射的实现方式:第一种 /*Class studentClass = Student.class; studentClass.getClass();*/ //第二种实现方式 Method[] methods = javaBean.getClass().getMethods(); // 获取所有方法 //第三种实现方式 /*Class.forName("类路径");*/ String fileName = null; File file = null; for (Method method : methods) { if (method.getName().startsWith("get")) { String field = method.getName(); // 拼接属性名 if (field.contains("getClass")) { continue; } field = field.substring(field.indexOf("get") + 3); Object value = method.invoke(javaBean, (Object[]) null); // 执行方法 if (field.equals("USER_SIGN_FILE") || field.equals("PORTRAIT")) { fileName = field; file = (File) value; continue; } if (fileName != null) { map.put(fileName, file); fileName = null; } else { map.put(field, value); } } } return map; } /** * 递归调用让字符串对中调换 * * @param originStr * @return String * @date 2021/01/11 */ public static String reverse(String originStr) { if (originStr == null || originStr.length() <= 1) return originStr; String substring = originStr.substring(1); String s = reverse(substring) + originStr.charAt(0); return s; } }