juanboy

app rebuilt

1 -from flask import Flask, render_template, request  
2 - 1 +import os
  2 +import subprocess
  3 +import threading
  4 +from flask import Flask, render_template, request, redirect, url_for, flash
  5 +from werkzeug.utils import secure_filename
3 import json 6 import json
  7 +
4 app = Flask(__name__) 8 app = Flask(__name__)
5 app.config['UPLOAD_FOLDER'] = 'data/' # 上传文件的保存目录 9 app.config['UPLOAD_FOLDER'] = 'data/' # 上传文件的保存目录
  10 +app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 文件大小限制为16MB
  11 +app.secret_key = 'secret_key' # 用于Flash消息的密钥
6 ALLOWED_EXTENSIONS = {'csv'} # 允许的文件扩展名 12 ALLOWED_EXTENSIONS = {'csv'} # 允许的文件扩展名
7 processing_status = {} # 全局字典用于存储处理状态和统计信息 13 processing_status = {} # 全局字典用于存储处理状态和统计信息
8 14
  15 +def allowed_file(filename):
  16 + """检查文件是否是允许的类型"""
  17 + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
  18 +
9 @app.route('/') 19 @app.route('/')
10 def upload_form(): 20 def upload_form():
11 """显示文件上传表单""" 21 """显示文件上传表单"""
12 return render_template('main.html') 22 return render_template('main.html')
13 23
  24 +@app.route('/status/<filename>')
  25 +def check_status(filename):
  26 + """检查文件处理状态,并返回状态和统计信息"""
  27 + status_info = processing_status.get(filename, {'status': 'processing', 'stats': None})
  28 + return json.dumps(status_info)
  29 +
14 @app.route('/waiting/<filename>') 30 @app.route('/waiting/<filename>')
15 def waiting_page(filename): 31 def waiting_page(filename):
16 """显示等待页面,并传递文件名""" 32 """显示等待页面,并传递文件名"""
@@ -29,3 +45,92 @@ def upload_failure(): @@ -29,3 +45,92 @@ def upload_failure():
29 filename = request.args.get('filename') 45 filename = request.args.get('filename')
30 stats = processing_status.get(filename, {}).get('stats', {}) 46 stats = processing_status.get(filename, {}).get('stats', {})
31 return render_template('failure.html', stats=stats) 47 return render_template('failure.html', stats=stats)
  48 +
  49 +def handle_file_processing(filepath, filename):
  50 + """异步处理文件并根据统计结果设置处理状态"""
  51 + try:
  52 + script_path = r'E:\ICTfront\BCAT\using_example.py' # 请根据实际路径更新
  53 + stats_output_path = os.path.join(app.config['UPLOAD_FOLDER'], f'stats_{filename}.json')
  54 +
  55 + # 执行外部脚本,传递文件路径和统计信息文件路径作为参数
  56 + result = subprocess.run(
  57 + ['python', script_path, filepath, stats_output_path],
  58 + stdout=subprocess.PIPE,
  59 + stderr=subprocess.PIPE,
  60 + text=True,
  61 + encoding='utf-8'
  62 + )
  63 +
  64 + print(f"脚本标准输出: {result.stdout}")
  65 + print(f"脚本标准错误: {result.stderr}")
  66 +
  67 + if result.returncode == 0:
  68 + # 读取统计信息
  69 + with open(stats_output_path, 'r', encoding='utf-8') as f:
  70 + stats = json.load(f)
  71 +
  72 + # 获取“不良”标签的占比
  73 + bad_percentage = float(stats.get("不良", {}).get("percentage", "0%").strip('%'))
  74 +
  75 + if bad_percentage > 5.0:
  76 + # 失败占比超过5%,标记为失败
  77 + processing_status[filename] = {
  78 + 'status': 'failure',
  79 + 'stats': stats
  80 + }
  81 + else:
  82 + # 成功
  83 + processing_status[filename] = {
  84 + 'status': 'success',
  85 + 'stats': stats
  86 + }
  87 + else:
  88 + # 脚本执行失败
  89 + processing_status[filename] = {
  90 + 'status': 'failure',
  91 + 'stats': None
  92 + }
  93 + except Exception as e:
  94 + print(f"运行脚本时出错: {str(e)}")
  95 + processing_status[filename] = {
  96 + 'status': 'failure',
  97 + 'stats': None
  98 + }
  99 +
  100 +@app.route('/upload', methods=['POST'])
  101 +def upload_file():
  102 + """处理文件上传和启动异步处理"""
  103 + if 'file' not in request.files:
  104 + flash('没有文件部分', 'error')
  105 + return redirect(url_for('upload_form'))
  106 +
  107 + file = request.files['file']
  108 +
  109 + if file.filename == '':
  110 + flash('未选择文件', 'error')
  111 + return redirect(url_for('upload_form'))
  112 +
  113 + if file and allowed_file(file.filename):
  114 + filename = secure_filename(file.filename)
  115 + filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
  116 + filepath = os.path.abspath(filepath) # 转换为绝对路径
  117 +
  118 + try:
  119 + file.save(filepath)
  120 + print(f'文件已保存到 {filepath}')
  121 +
  122 + # 初始化处理状态
  123 + processing_status[filename] = {'status': 'processing', 'stats': None}
  124 +
  125 + # 启动后台线程处理文件
  126 + thread = threading.Thread(target=handle_file_processing, args=(filepath, filename))
  127 + thread.start()
  128 +
  129 + # 重定向到等待页面,并传递文件名以跟踪状态
  130 + return redirect(url_for('waiting_page', filename=filename))
  131 + except Exception as e:
  132 + flash(f'文件上传失败: {str(e)}', 'error')
  133 + return redirect(url_for('upload_failure'))
  134 + else:
  135 + flash('文件类型不允许', 'error')
  136 + return redirect(url_for('upload_form'))