zoukankan      html  css  js  c++  java
  • Java之利用openCsv导出csv文件

    当时导入的时候用的openCsv,那么导出的时候自然也是用这个,查了好多资料才找到解决方案,下面记录一下实现过程。

    1.Controller层:

    /**
     * 导出csv文件
     */
    @RequestMapping("/exportcsv")
    @RequiresPermissions("xxx:xxxx:xxx")
    public String exportCsv(@RequestBody List<xxxEntity> exportResults, HttpServletResponse response) {
        return xxxService.exportCsvFile(exportResults, response);
    }

    2.实现类部分:

    @Override
    public String exportCsvFile(List<xxxEntity> exportResults, HttpServletResponse response) {
        try {
            CSVUtils<xxxEntity> xxx = new CSVUtils();
            xxx.generateCsvFile(exportResults, "exportResults.csv", HEADER);
            xxx.readCsvFileStream("exportResults.csv", response);
        } catch (IOException | CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
            log.error("EXPORT ERROR", e);
        }
        return null;
    }

    3.核心Util导出方法:

    import com.opencsv.CSVWriter;
    import com.opencsv.bean.StatefulBeanToCsv;
    import com.opencsv.bean.StatefulBeanToCsvBuilder;
    import com.opencsv.exceptions.CsvDataTypeMismatchException;
    import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.util.List;
    
    /**
     * CSV 工具类
     *
     * @author jing
     */
    @Slf4j
    @Component
    public class CSVUtils<T>{
    
        /**
         * 将前台传递的数据生成csv文件
         * @param exportResults
         * @param fileName
         * @param header
         * @throws IOException
         * @throws CsvDataTypeMismatchException
         * @throws CsvRequiredFieldEmptyException
         */
        public static<T> void generateCsvFile(List<T> exportResults, String fileName, String[] header) throws IOException, CsvDataTypeMismatchException, CsvRequiredFieldEmptyException {
            Writer writer = new FileWriter(fileName);
            // 写表头
            CSVWriter csvWriter = new CSVWriter(writer, CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.NO_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END);
            csvWriter.writeNext(header);
            //写内容
            StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer).build();
            beanToCsv.write(exportResults);
            csvWriter.close();
            writer.close();
        }
    
        /**
         * 读取csv文件流返回前端下载
         * @param fileName
         * @param response
         * @throws UnsupportedEncodingException
         */
        public static void readCsvFileStream(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
            String myFileName = new String(fileName.getBytes("utf-8"), "gbk");
            File file = new File(myFileName);
            if (file.exists()) {
                response.setContentType("application/force-download");// 设置强制下载不打开
                response.addHeader("Content-Disposition", "attachment;fileName=" + myFileName);// 设置文件名
                byte[] buffer = new byte[1024];
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                try {
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis);
                    OutputStream os = response.getOutputStream();
                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (bis != null) {
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            if(file.delete()){
                log.error(file.getName() + " 文件已被删除!");
            }else{
                log.error("文件删除失败!");
            }
        }
    
    }

    这里的思路是后端接收前端发来的list,然后利用openCsv写入生成csv文件,再从csv文件中读取文件流返回前端下载。

    下面是项目中的两个问题:

    1.如果不指定csv文件中的顺序,那么他是基于列名升序排列,那么这里就需要用@CsvBindByPosition(position = 0)来定位位置,但是如果你用这个来定位的话,那么表头就展示不出来,如果@CsvBindByName的话,又定位不了位置,那么这里我的解决方案就是,用@CsvBindByPosition(position = 0)来定位位置,表头的话再自己写入。

    2.如果列中出现了时间相关的数据,那么他展示的数据是GMT+8这种格式,这时候的解决方案是用@CsvDate("yyyy-MM-dd HH:mm:ss")来进行时间格式化。

    我的实体类大概长这样儿:

    /**
     * 用户
     */
    @Data
    @TableName("user")
    public class UserEntity implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @TableId
        @CsvBindByPosition(position = 0)
        private Long id;
        /**
         * 用户名
         */
        @NotBlank(message = "用户名不能为空")
        @CsvBindByPosition(position = 1)
        private String userName;
        /**
         * 创建时间
         */
        @CsvBindByPosition(position = 2)
        @CsvDate("yyyy-MM-dd HH:mm:ss")
        @JSONField(format = "yyyy-MM-dd HH:mm:ss")
        @TableField(fill = FieldFill.INSERT)
        private Date createTime;
        /**
         * 修改时间
         */
        @CsvBindByPosition(position = 3)
        @CsvDate("yyyy-MM-dd HH:mm:ss")
        @JSONField(format = "yyyy-MM-dd HH:mm:ss")
        @TableField(fill = FieldFill.UPDATE)
        private Date updateTime;
    }

    这中导出方式需要有一个中间文件csv的生成,如果有更好的方法,欢迎评论区留言。

  • 相关阅读:
    oracle常用命令(比较常见好用)
    vim编辑器详解
    对话框和打印控件
    winform弹出唯一的窗体
    ListView
    菜单栏和布局
    窗体属性和公共控件
    ASPCMS和WPF
    MVC
    正则表达式
  • 原文地址:https://www.cnblogs.com/ailanlan/p/12172952.html
Copyright © 2011-2022 走看看