之前同事寫了前端表格導出的功能, 前后端邏輯沒有梳理, 導致后端代碼十分臃腫.
接手之后, 重新選擇了前端table插件, 從jqxGrid變更為bootstrapTable.
本來想依賴集成的tableExport.js在前端自己實現文件下載的, 然而這個插件存在着諸多不理想的地方.
首先導出的文件格式, excel會提示文件格式損壞報錯; 其次長串數字會被截斷, 並且以科學計數顯示. 在bootstrapTable中將值toString依然無效.
搜索了一下前端的解決方案, 最后還是決定在后端做實現.
第一個方案是打算做一個緩存機制. 前端查詢一次后, 在后端緩存結果, 接口返回數據和cacheId. 當要導出文件時, 前端通過cacheId去請求緩存數據的下載.
然而這種方案雖然合理, 但緩存機制的細節處理較為繁瑣, 糾結了一下, 暫時放棄.
如果不做緩存的話, 每次導出都需要重新去做查詢, 不但耗時較長, 機制也比較蠢.
最后在前同事的方案上做了些許改進. 前端首先向服務器post自己的table數據, 后端處理成excel之后再返回. 這種方案不適合大量數據導出. 數據量大的話, 網絡傳輸也會成為問題.
代碼主要有三部分, 前端業務邏輯, 前端抽象函數, 后端抽象接口.
業務邏輯:
$('#table-export').click(function(){ var currentPage = window.location.pathname; // 文件命名參數 var tableData = $('#table').bootstrapTable('getData'); // table數據 var colnames = [ {'field':'a', 'title': '國家'}, {'field':'b', 'title':'代碼'}, {'field':'c', 'title':'抽象'}, {'field':'d', 'title': '初音'}, {'field':'e', 'title': '日期'}, ] if (tableData.length == 0) { makeAlert('danger', '沒有可導出數據!', $('#query-alert')); // 錯誤提示 return false; } exportExcel(tableData, colnames, currentPage); })
前端抽象函數:
// 通過form提交實現. 用ajax post也可以, 但實現方式另有不同, 沒有選擇. // 參數含data, 列名, 調用頁面的名稱 function exportExcel(data, colnames, page) { var targetUrl = $SCRIPT_ROOT + '/api/v1.0/export_excel/'; var temp = document.createElement("form"); temp.action = targetUrl; temp.method = "post"; temp.style.display = "none"; var tableData = document.createElement("textarea"); tableData.name = "table_data"; tableData.value = JSON.stringify(data); temp.appendChild(tableData); var columnName = document.createElement("textarea"); columnName.name = "colnames"; columnName.value = JSON.stringify(colnames); temp.appendChild(columnName); var pageName = document.createElement("textarea"); pageName.name = "pageName"; pageName.value = JSON.stringify(page); temp.appendChild(pageName); document.body.appendChild(temp); temp.submit(); return false; }
后端接口:
# 依賴flask-excel make response 實現xls文件返回 # flask-excel存在很多坑, 耐心點踩 from flask import request from . import api from app.utils import format_datetime import flask_excel as excel import json import datetime @api.route('/export_excel/', methods=['POST']) def export_excel(): if request.method == 'POST': table_data = json.loads(request.form['table_data']) colnames = json.loads(request.form['colnames']) page_name = request.form['pageName'].split('/')[-1] file_name = '{}_{}'.format(page_name, format_datetime(datetime.datetime.now(),'%Y%m%d%H%M%S')) excel_resp = make_excel_list(table_data, colnames) return excel.make_response_from_array(excel_resp, 'xlsx', sheet_name = page_name, file_name= file_name) else: return False def make_excel_list(data, fields): list_data = [] field = [x['field'] for x in fields] name = [x['title'] for x in fields] list_data.append(name) for item in data: tmp = [] for fi in field: if fi in item.keys(): tmp.append(item[fi]) else: tmp.append('') list_data.append(tmp) return list_data