FineReport调用python服务进行大数据量导出

回帖奖励 1300 个F豆      回复本帖可获得 20 个F豆奖励! 每人限 1 次
楼主
我是社区第384017位番薯,欢迎点我头像关注我哦~

Finereport调用python服务进行大数据量导出

Aerial view of woman using a computer laptop on a marble table

 

背景:

在使用finereport过程中,我们发现在数据导出这块一直是一个瓶颈,闲来无事,思索一番,想出来一种场景来应对此问题。供各位大佬参考讨论,也欢迎其他大佬提供更好的解决方案。

 

文笔较差,大佬见谅。

 

废话不多说,直接上代码,案例。

 

正文:

首先,我们需要使用python启一个flask服务,来供传递参数,sql等。

本次举例写的固定sql,后续大家可以自行优化扩展。

1.启动flask服务

from flask import Flask, request, jsonify, send_file
import pymysql
import pandas as pd
import threading
import os
import time

app = Flask(__name__)

# 数据库连接配置
db_config = {
   'host': 'ip',
   'user': '用户',
   'password': '密码',
   'database': '数据库'
}

# 数据库连接
def connect_db():
   return pymysql.connect(**db_config)

# 导出到CSV函数
def export_to_csv(sql, params, output_file):
   connection = connect_db()
   try:
       # 执行查询并使用参数化查询
       with connection.cursor() as cursor:
           cursor.execute(sql, params)  # 使用参数化查询
           result = cursor.fetchall()

           # 如果没有结果,返回None
           if not result:
               return None

           # 将查询结果转换为DataFrame并写入CSV
           df = pd.DataFrame(result, columns=[i[0] for i in cursor.description])
           df.to_csv(output_file, index=False, encoding='utf-8')

           print(f"CSV文件已生成: {output_file}")
           return output_file
   finally:
       connection.close()

# 后台线程处理文件导出
def generate_csv(sql, params, output_file):
   export_to_csv(sql, params, output_file)

# 这里为了验证场景使用的get请求,实际大多数情况下都需要传递参数,推荐post请求。
@app.route('/run_report', methods=['GET'])
def run_report():
   params = request.args.getlist('params')  # 获取URL查询参数
   sql = "SELECT * FROM test_table"  # 默认的SQL查询

   # 生成唯一的输出文件名(可以用时间戳或UUID)
   output_file = f'output_{int(time.time())}.csv'

   # 启动后台线程生成CSV文件
   thread = threading.Thread(target=generate_csv, args=(sql, params, output_file))
   thread.start()

   # 等待线程完成,确保文件生成后直接返回文件
   thread.join()  # 确保线程完成后返回

   # 如果文件生成成功,直接返回文件
   if os.path.exists(output_file):
       return send_file(output_file, as_attachment=True, mimetype='text/csv')
   else:
       return jsonify({'error': '生成CSV文件失败'}), 500

if __name__ == '__main__':
   app.run(debug=True)

 

2.创建模板:

在按钮点击事件上绑定服务地址即可。

提示这块目前做的比较粗糙,大家可以自行优化。


window.location.href="http://127.0.0.1:5000/run_report"
FR.Msg.alert("提示","数据正在下载请稍后");

3.示例模板

后台导出.rar (1.99 K)

4.示例操作

 

不知道怎么上传视频,大家自己尝试吧

 

第一次写技术文章,写的不咋好,大家见谅,感谢。顺便吐槽一句,这个发帖写作的好难使用啊。

 

目前仅为思路的验证,代码健壮性目前比较差,见谅。

分享扩散:
参与人数 +1 F豆 +32 理由

查看全部评分

沙发
发表于 15 分钟前

回帖奖励 +20 个F豆


思路不错,补充几个需要调整的地方或者后面迭代的方向:
1、基于flask暴露接口,就意味着你需要重新部署一个服务,可以换个思路使用java开发,将其集成到FR自身的工程中。
2、目前这样的接口存在两个问题,一个是网络环境问题,一个是安全性问题,因为控制不了权限,所以通过访问下载文件的原URL就可以肆无忌惮的下载文件。
3、为了解决上面的问题,可以试着和FR的session结合一下,做一下鉴权。
4、最后接口一定要对传参数据做一下SQL注入校验
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1回帖数 1关注人数 106浏览人数
最后回复于:15 分钟前

返回顶部 返回列表