jfinal layui easyexcel 實現文件的上傳下載


 

jfinal  layui easyexcel  這三樣開源技術這里就不多介紹了,自行百度了解吧,他們的組合算是一個很高效又不失美觀的操作體驗。

操作主要分以下幾步:

1、建立jfinal的操作環境,建議使用作者提供的demo , 創建一個 jfinal + undertow 的運行環境。undertow運行起來很快,不僅方便調試,而且運行穩定。https://www.jfinal.com/doc

2、引入easyexcel的相關包,我這里使用的是2.0.5版本,網上有很多1.2的版本教程,這里使用的最新的版本,同老版本還是有些區別的,作者提供了相關的demo,可以自己試一下。

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>test</scope>
</dependency>

 3、建立你要導入的數據庫表,我這里用的是mysql5.7,並編寫你的導入模板。這里就不貼圖了,自己親手做下就行。

4、分別創建幾個類文件 jfinal的controller 、service ,easyexcel使用的 excelData、excelDataListener 文件,當然還有前端訪問的excelupload.html頁面。

easyexcel 使用 Data文件來約束模板文件的標題(頭文件),導入字段的類型和excel中cell的順序

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;

/**
 * 基礎數據類.用於基礎數據表的導入
 * 這里的排序和excel里面的排序一致
 *
 * @author 
 **/
@Data //使用注解來格式該文件
@HeadRowHeight(20) // 作為導出data的時候設置頭文件行高
@ContentRowHeight(20) //作為導出data的時候設置內容行高
@ColumnWidth(25)//設置行寬
public class ExcelData {

    @ExcelProperty(value = "工號", index = 0) //這里的工號是和excel的標題一致,index 表示第幾列數據
    private String agentcode;
    @ExcelProperty(value = "姓名", index = 1)
    private String name;
    @ExcelProperty(value = "手機號", index = 2)
    private String mobile;
    @ExcelProperty(value = "身份證號", index = 3)
    private String idno;
    @ExcelProperty(value = "執業證號", index = 4)
    private String certifno;
    @ExcelProperty(value = "機構代碼", index = 5)
    private String agentgroupcode;
    @ExcelProperty(value = "機構名稱", index = 6)
    private String agentgroupname;

    public String getAgentcode() {
        return agentcode;
    }

    public void setAgentcode(String agentcode) {
        this.agentcode = agentcode;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getIdno() {
        return idno;
    }

    public void setIdno(String idno) {
        this.idno = idno;
    }

    public String getCertifno() {
        return certifno;
    }

    public void setCertifno(String certifno) {
        this.certifno = certifno;
    }

    public String getAgentgroupcode() {
        return agentgroupcode;
    }

    public void setAgentgroupcode(String agentgroupcode) {
        this.agentgroupcode = agentgroupcode;
    }

    public String getAgentgroupname() {
        return agentgroupname;
    }

    public void setAgentgroupname(String agentgroupname) {
        this.agentgroupname = agentgroupname;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

easyexcel的ExcelDataListener 文件 是解析excel時候使用的監聽,在讀取一行數據的時候都要調用invoke()方法,在解析完excel之后執行 doAfterAllAnalysed() 方法,demo中提供了分批次處理的方法

public class ImBnExcelDataListener extends AnalysisEventListener<ImpBnExcelData> {

    private static final Log log = Log.getLog(ImBnExcelDataListener.class);
    /**
     * 每隔5條存儲數據庫,實際使用中可以500條,然后清理list ,方便內存回收
     */
    private static final int BATCH_COUNT = 500;

    List<ImpBnExcelData> list = new ArrayList<ImpBnExcelData>();
    StringBuilder stringBuilder = new StringBuilder();

    @Override
    public void invoke(ImpBnExcelData data, AnalysisContext context) {
        System.out.println("解析到一條數據:{}"+JSON.toJSONString(data));
        list.add(data);
/*        list.add(data);
        if (list.size() >= BATCH_COUNT) {
            System.out.println("解析到一條數據:{}"+data.getAgentcode());
            saveData(list);
            list.clear();
        }else {
            saveLastData(list);
            list.clear();
        }*/
        //saveDataByOne(data);
        stringBuilder.append("(");
        //BnController BnController =new  BnController();
        String convertdata =convertToStr(data);
        stringBuilder.append(convertdata);
        stringBuilder.append("),");
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        String sqlpro = stringBuilder.toString().substring(0,stringBuilder.toString().lastIndexOf(","));
        System.out.println(sqlpro);
        batchInsert(sqlpro);
        //saveDataObj(convertToObj(list));
        System.out.println("所有數據解析完成!");
    }

    public String convertToStr(ImpBnExcelData data){
        String convertdata = "'"+data.getAgentcode()+"','"
                +data.getName()+"','"
                +data.getMobile()+"','"
                +data.getIdno()+"','"
                +data.getCertifno()+"','"
                +data.getAgentgroupcode()+"','"
                +data.getAgentgroupname()+"','"
                +DateUtil.getTodaySecNum()+"','"
                +DateUtil.getTodaySec()+"'";
        return convertdata;
    }
    public static void batchInsert(String sqlpro) {
        long start = System.currentTimeMillis();
        Config config = DbKit.getConfig("datasource");
        Connection conn = null;
        try {
            conn = config.getConnection();
            conn.setAutoCommit(false);
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append("insert into table (xx,name,mobile,idno,xx,xx,xx,xx,uptime) values ");
            stringBuffer.append(sqlpro);
            PreparedStatement pst = conn.prepareStatement(stringBuffer.toString());
            pst.addBatch();
            pst.executeBatch();

            conn.commit();

            pst.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("批量插入需要時間:"+(end - start)); //批量插入需要時間:24675
    }

這里我使用了合成 insert value 值的方法,將讀取的excel拼接成一條 insert into 語句,這樣會大大提升批量存儲效率,比一條條存要快的多,如果你的mysql接收sql語句的長度夠,可以寫成一條語句,如果不行就要分批進行存儲,或者修改mysql.ini的 參數,將max_allowed_packet的值改大就行,這里我修改到了16M。 jfinal提供了多數據源多配置的方法可以使用 DbKit.getConfig() 或Db.use("")的方法直接使用數據源或直接調用jdbc,方便的不要不要的。

Controller 文件是jfinal用來做控制轉發的文件,設置好路由之后,直接可以用Controller調用相關方法,在web環境下運行改方法。

public void upbnexcel() {
        AjaxMsg ajaxMsg = new AjaxMsg();
        try {
            String webrootpath = PathKit.getWebRootPath();
            //設置文件上傳子目錄
            //String path = "uploads/excel/";
            String path =PropKit.get("excel_upload_path");
            UploadFile upload = getFile("file", webrootpath + File.separator + path);
            File file = upload.getFile();
            //獲取文件名
            String extName = FileUtils.getFileExt(file.getName());
            //獲取文件上傳的父目錄
            String filePath = upload.getUploadPath();
            //時間命名文件
            String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + extName;
            //重命名原來的文件
            file.renameTo(new File(filePath + fileName));
            long start = System.currentTimeMillis();
            EasyExcel.read(filePath+fileName, ExcelData.class, new ExcelDataListener()).sheet().doRead();
            log.info("導入耗時s:"+String.valueOf((System.currentTimeMillis()-start)/1000));
            ajaxMsg.setState("success");
            ajaxMsg.setMsg("上傳成功,耗時"+String.valueOf((System.currentTimeMillis()-start)/1000)+"秒");
        } catch (Exception e) {
            e.printStackTrace();
            ajaxMsg.setState("fail");
            ajaxMsg.setMsg("上傳失敗:"+e.getMessage());
        }
        renderJson(ajaxMsg);
    }

通過web方法,先將excel上傳到服務器的upload/excel文件夾下,並通過時間進行命名,然后直接調用 EasyExcel.read方法解析並寫入數據庫,然后通過ajaxMsg返回頁面狀態提示。這里有個注意

UploadFile upload = getFile("file", webrootpath + File.separator + path); 中的 "file" 是cos中的約束,必須要這么寫,否則會上傳失敗
EasyExcel.read 提供了很多讀取的方式,可以選取自己需要的方式進行調整。調整后別忘關閉操作流。

uploadexcel.html頁面引入了layui相關框架,引入的包就不羅列了,直接寫相關內容

<body>
<div id="app" class="layui-form">
    <div class="container">
        <div class="layui-form-item">
            <a class="layui-btn layui-btn-warm" href="模板.xlsx" target="_blank">模板下載</a>
        </div>
        <blockquote class="layui-elem-quote">
        <form class="layui-form" action="">
            <div class="layui-form-item">
                <div class="layui-inline">
                    <div class="layui-upload">
                        <button type="button" class="layui-btn layui-btn-normal" id="file">選擇文件</button>
                        <button type="button" class="layui-btn" id="updo">開始上傳</button>
                    </div>
                </div>
            </div>
        </form>
        </blockquote>
    </div>
</div>
</body>
<script src="../../../static/plugins/layui/layui.js"></script>
<script>
    //一般直接寫在一個js文件中
    layui.use(['layer', 'form', 'upload'], function () {
        var layer = layui.layer
            , form = layui.form
            , upload = layui.upload;

        //選完文件后不自動上傳
        var uploadInst = upload.render({
            elem: '#file'
            , url: '/upexcel'
            , auto: false
            , accept: 'file' //普通文件
            //,multiple: true
            , bindAction: '#updo'
            , done: function (res) {
                //上傳完畢回調
                if (res.state == "success") {
                    parent.layer.alert(res.msg);
                }
                else {
                    parent.layer.alert(res.msg);
                    return false;
                }
            }
        });
    })
}

下載操作比較簡單,注意一下 ajax不能直接下載文件,需要通過 action 或 href 來下載  ,這里我做了兩步請求,先通過選擇列表中需要下載的項,然后執行id序列化操作,然后再次執行查詢和下載操作,才能保存下載的excel文件。

        $("#expdata").on('click', function () {
            var checkStatus = table.checkStatus('tablelist'), data = checkStatus.data;
            var ids = [];
            for (var i = 0; i < data.length; i++) {
                ids.push(data[i].id);
            }
            console.log(ids);
            $.ajax({
                //type: 'post',
                url: '/downExcel',
                data: {ids: ids},
                success: function (response) {
                    console.log(response.idstr);
                    window.location.href="/expExcel?idstr="+response.idstr;
                },
            });
        });

 

 /**
     * 導出excel
     */
    public void expExcel(){
        try {
            //String[] ids = getParaValues("ids[]");
           String idstr = getPara("idstr");
            HttpServletResponse response=getResponse();
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 這里URLEncoder.encode可以防止中文亂碼 當然和easyexcel沒有關系
            String fileName = URLEncoder.encode("測試", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=demo.xlsx");
            EasyExcel.write(response.getOutputStream(), ExcelData.class).sheet("模板").doWrite(downExceldata(idstr));
           // EasyExcel.write(fileName, ImpBnExcelData.class).sheet("模板").doWrite(data());
        }catch (Exception e){
        }
        renderNull();
        //renderFile(file,"demo.xlsx");
    }
  //下載時候首先執行該方法,並將選中的id拆分組合為字符串,再將字符串進行回傳
public void downExcel(){ String[] ids = getParaValues("ids[]"); String idstr = Arrays.toString(ids); idstr = idstr.substring(1, idstr.length() - 1); renderJson("idstr",idstr); } public List<ImpBnExcelData> downExceldata(String idstr){ List<Record> lists =BnService.me().findByIdstr(idstr); List<ImpBnExcelData> bndatalist = new ArrayList<>(); for(Record record : lists) { ImpBnExcelData bnExcelData = new ImpBnExcelData(); ExcelData.setAgentcode(record.getStr("agentcode")); ExcelData.setAgentgroupcode(record.getStr("agentgroupcode")); ExcelData.setAgentgroupname(record.getStr("agentgroupname")); ExcelData.setCertifno(record.getStr("certifno")); ExcelData.setIdno(record.getStr("idno")); ExcelData.setMobile(record.getStr("mobile")); ExcelData.setName(record.getStr("name")); datalist.add(bnExcelData); } return bndatalist; }

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM