大批量數據導出/前端導出數據實踐

場景

我們PHP程序員在整個工作流程中,難免要和CRM/ERP之類的系統打交道。數據表格導出是在常見不過的功能模塊。在數據量比較小的時候,我們可以隨便搞,直接設置header頭,輸出csv也是可以的。但是當數據量上來的時候,我們會面臨但不侷限於以下問題:

1.php腳本執行超時;

2.可用內存不足;

3.nginx超時。

解決方案

所以很自然的想到,那能不能把文件下載/導出/保存這個動作放到前端來執行呢,這樣還可以節省服務器資源。我覺得這是個不錯的主意。
先上代碼

 //依賴的JS工具庫
 //github https://github.com/sheetjs/sheetjs
 <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
 exportData() {
                    //dialog控制開關
                    this.dialogVisible = true;
                    /* original data */
                    let date = new Date();
                    let filename = date.getFullYear() + '' + (date.getMonth() + 1) + '' + date.getDate() + "列表.xlsx";
                    let insertData = [];
                    let header = [
                        '用戶id',
                        '手機號',
                        '姓名'
                    ];
                    insertData.push(header);
                    //在vue裏爲了不影響數據做一下深拷貝
                    let tmpData = JSON.stringify(this.$data);
                    let tmpParamObj = JSON.parse(tmpData);
                    let totalPage = this.total_page;
                    let totalCount = this.total_count;
                    const that = this;
                    for (let i = 1;i<=totalPage;i++) {
                        tmpParamObj.current_page = i;
                        //去掉沒用的數據
                        tmpParamObj.list = [];
                        tmpParamObj.pagination = [];
                        $.ajax({
                            url: '/demo/demo/demo/getList',
                            method: 'POST',
                            data: {'_token': '{{csrf_token()}}', data: tmpParamObj},
                            success: function (data) {
                                console.log(data);
                                if (data.status == 'success') {

                                    data.data.forEach((item, index) => {
                                        let tmp = [];
                                        tmp.push(item.PassportID);
                                        tmp.push(item.MobileNumber);
                                        tmp.push(item.RealName);
                                        insertData.push(tmp);
                                    });
                                    //記錄下載進度更新到dialog上的下載進度條
                                    let percent = Number.parseInt((insertData.length - 1) / totalCount * 100);
                                    console.log(percent);
                                    that.download_percent = percent;
                                    if (percent === 100) {
                                        let ws_name = "SheetJS";
                                        let wb = XLSX.utils.book_new();
                                        let ws = XLSX.utils.aoa_to_sheet(insertData);
                                        //
                                        /* add worksheet to workbook */
                                        XLSX.utils.book_append_sheet(wb, ws, ws_name);
                                        console.log('【開始下載】' + new Date());
                                        XLSX.writeFile(wb, filename);
                                        console.log('【下載完成】' + new Date());
                                        that.dialogVisible = false;
                                    }
                                } else {
                                    layer.msg('請求失敗', {icon: 2});
                                }
                            },
                            dataType: 'json',
                            error: function () {
                                layer.msg('網絡異常', {icon: 2}, function () {
                                    layer.closeAll();
                                });
                            }
                        });
                    }
                }



循環的按照頁碼去請求數據,直到拿到所有的數據。然後一併保存。理論上可以不擔心數據的體量。新技能Get。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章