最近有需要导出用户留言的数据,包含用户留言的上传的照片

java 导出图表 设置图表点的数据展示 java导出excel能导出图片吗_java导出excel表格


在网上找了很多,整合一些,最后实现了业务,导出来有点丑,后续再做优化,代码功能有局限性,看到的小伙伴如果有好的想法可以说说,让我学习学习

最后实现的效果(似乎一个格子不能放多张图片?)

java 导出图表 设置图表点的数据展示 java导出excel能导出图片吗_java_02


直接上代码:

导入maven依赖

<!-- poi读取excle -->
	<dependency>
		<groupId>org.apache.poi</groupId>
		<artifactId>poi</artifactId>
		<version>3.9</version>
	</dependency>

Controller类

/**
	 * 下载用户留言信息
	 * @date 2021/01/11
	 * @param query
	 * @param request
	 * @param response
	 */
	@ApiOperation(value = "下载用户留言信息",
			notes = "")
	@RequestMapping(value="exeportData",method={RequestMethod.POST,RequestMethod.GET})
	public void exeportData(@RequestBody(required=false) UserMessageQuery query, HttpServletRequest request, HttpServletResponse response) throws Exception {
		if(query==null){
			query = new UserMessageQuery();
		}
		query.setVenderId(PublicUtil.getCustomerId()); //这是我的查询条件
        //查询任务
        List<UserMessage> data = userMessageService.selectList(query);

        Map<String, Object> objMap = new HashMap<>();
        List<Map<String,Object>> list = new ArrayList<>();
		String path= "/data/nginxd/sportsApplets/excelDeleteImage/";
        if(data.size()>0){
            for (UserMessage userMessage: data) {
                //通过留言id去获取留言上传的图片列表
                List<String> imgList = userMessageImgService.selectImg(userMessage.getId());
                UserMessageExcel excelObj = new UserMessageExcel();
                excelObj.setNickName(userMessage.getNickName());
                excelObj.setCreateTime(PublicUtil.getDateString(userMessage.getCreateTime()));
                excelObj.setContent(userMessage.getContent());

                File[] files = new File[imgList.size()];
                if(imgList.size()>0){
                    for (int i =0 ; i< imgList.size(); i++){
						String filePath = ImageExcelUtil.saveFile(imgList.get(i), path);  //由于我的是远程服务器的网络图片,所以我先保存到本地,如果是本地服务器图片,不需要保存这一步
						files[i] = new File(filePath);
                    }
                }
                excelObj.setImages(files);
				objMap = ImageExcelUtil.javaBean2Map(excelObj);
                list.add(objMap);
            }
        }
        Object[] objects = objMap.keySet().toArray();
        String[] titles = new String[objects.length];
        Map<String, String> map = getMap();
        for(int i=0;i<titles.length;i++){
            String key = objects[i].toString();
            titles[i] = map.get(key);
        }

		String fileName = "用户留言信息记录"+PublicUtil.getShortDateString(new Date());
		response.setContentType("application/vnd.ms-excel");
		response.addHeader("Content-Disposition", "attachment; filename="+fileName);
        ImageExcelUtil.excelOut(titles,list.size(),list,fileName, response, path);
	}

	/**
	 * 每一列数据的标题
	 * @date 2021/01/11
	 * @return Map<String,String>
	 */
	public Map<String, String> getMap(){
		Map<String, String> map = new HashMap<>();
		map.put("nickName","用户昵称");
		map.put("createTime","留言时间");
		map.put("content","留言内容");
		map.put("images","图片");
		return map;
	}

导出工具类:

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 javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ImageExcelUtil {
    
    private static final Log log = LogFactory.getLog(ImageExcelUtil.class);

    /**
     * excel工具类,可导出带图片或不带图片的数据
     * @date 2021/01/11
     * @param titles 第一行的标题列
     * @param rows 数据行量
     * @param maps 装载导出数据的封装了map的list数据集合,注意:此中的map尽量用本类中的方法 javaBean2Map直接生成,或自己拼接;但需与参数titles[]的标题相关数据对应上
     * @param fileName 导出到本地的文件路径和文件名
     * @param response response
     * @param path 保存到本地的图片地址(我这里是为了删除该目录下的图片,因为我是把网络图片保存到到本地的,如果图片已经是本地图片的话就不需要删除)
     */
    public static void excelOut(String[] titles, int rows, List<Map<String,Object>> 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(25);
                //行数据处理
                Map<String, Object> stringObjectMap = maps.get(i - 1);
                for(Object value : stringObjectMap.keySet()){
                    //行单元格
                    cellRow = row.createCell(cellColumn);
                    cellRow.setCellStyle(style);
                    //如果行数据中有图片时候的处理
                    if (value.equals("images")){
                        File[] file = (File[]) stringObjectMap.get(value);
                        if (file == null || file.length == 0){
                            cellRow.setCellValue("");
                            continue;
                        }else{
                            row.setHeightInPoints(50);

                            for (int x=0;x<file.length;x++){
                                ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
                                if (x>0){
                                    cellRow = row.createCell(cellColumn);
                                    cellRow.setCellStyle(style);
                                }
                                sheet.setColumnWidth(cellColumn,5000);
                                log.error("图片路径"+file[x]);
                                bufferImg = ImageIO.read(file[x]);
                                ImageIO.write(bufferImg, "jpg", byteArrayOut);
                                anchor = new HSSFClientAnchor(0, 0, 1023, 255,(short) cellColumn, i, (short) cellColumn, i);
                                anchor.setAnchorType(3);
                                patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
                                cellColumn++;
                            }
                            continue;
                        }
                    }
                    cellRow.setCellValue(stringObjectMap.get(value).toString());
                    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里面就删除)
     * @date 2021/01/11
     * @param file
     */
    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();
    }

    /**
     * 保存图片到本地
     * @date 2021/01/11
     * @param imageUrl
     * @param path
     * @return
     */
    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属性放置最后。
     * @date 2021/01/11
     * @param javaBean
     * @return Map
     * @throws Exception
     */
    public static Map<String, Object> javaBean2Map(Object javaBean) throws Exception {
        Map<String, Object> map = new LinkedHashMap<>();
        //反射的实现方式:第一种
        /*Class<Student> studentClass = Student.class;
        studentClass.getClass();*/
        //第二种实现方式
        Method[] methods = javaBean.getClass().getMethods(); // 获取所有方法
        //第三种实现方式
        /*Class.forName("类路径");*/
        String fileName = null;
        File[] files = 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);
                field = field.toLowerCase().charAt(0) + field.substring(1);
                Object value = method.invoke(javaBean, (Object[]) null); // 执行方法
                if (field.equals("images")){
                    fileName = field;
                    files = (File[]) value;
                    continue;
                }
                map.put(field, value);
            }
        }
        if (fileName != null){
            map.put(fileName,files);
        }
        return map;
    }

    /**
     * 递归调用让字符串对中调换
     * @date 2021/01/11
     * @param originStr
     * @return String
     */
    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;
    }

}

导出对象实体类:

import java.io.File;
import java.io.Serializable;
import java.util.Date;

public class UserMessageExcel implements Serializable{

    /**
     *序列化ID
     */
    private static final long serialVersionUID = 1L;
	/**
     * 用户昵称
     */
    private String nickName;
    /**
     * 创建时间(留言时间)
     */
    private String createTime;
	/**
     * 留言内容
     */
    private String content;
	/**
     * 图片数组
     */
    private File[] images;

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public File[] getImages() {
        return images;
    }

    public void setImages(File[] images) {
        this.images = images;
    }
}

总结

本代码扩张性不强,时间比较急,后续再慢慢优化,写此记录下