import os import sys import logging from flask import Flask from lib.config import load_config, get_web_config, get_limits_config from lib.log_handler import setup_logging from lib.db import init_database app = Flask(__name__, template_folder=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates'), static_folder=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static')) # MAX_CONTENT_LENGTH:SRS 9.1 要求 docx ≤1MB、image ≤256KB。 # JSON 请求体的 Base64 编码会让 docx 膨胀约 33%,叠加多图章项后取 4MB 比较保守。 # 真正的硬限制由 lib/validators.validate_docx_size 在解码后强制。 app.config['MAX_CONTENT_LENGTH'] = 8 * 1024 * 1024 from routes.pages import pages_bp from routes.api import api_bp from routes.db_api import db_api_bp from routes.batch_api import batch_api_bp from routes.monitor_api import monitor_api_bp app.register_blueprint(pages_bp) app.register_blueprint(api_bp) app.register_blueprint(db_api_bp) app.register_blueprint(batch_api_bp) app.register_blueprint(monitor_api_bp) def ensure_dirs(): base = os.path.dirname(os.path.abspath(__file__)) for d in ['temp', 'logs', 'output', 'data', 'static', 'static/css', 'static/js']: os.makedirs(os.path.join(base, d), exist_ok=True) def main(): load_config() setup_logging() ensure_dirs() logger = logging.getLogger(__name__) logger.info("===== 自动签名系统启动 =====") limits = get_limits_config() logger.info("限制配置: docx_max=%d bytes, image_max=%d bytes, stamp_max=%d, log_max=%d", limits['docx_max_bytes'], limits['image_max_bytes'], limits['stamp_max_count'], limits['log_max_entries']) try: ok = init_database(strict_mysql=False) if not ok: logger.error("数据库初始化失败(MySQL 不可用且 strict 模式)") else: from lib.db import get_active_db_type db_type = get_active_db_type() logger.info("数据库初始化完成, 当前使用: %s", db_type.upper()) except Exception as e: logger.error("数据库初始化失败: %s", str(e)) web_cfg = get_web_config() host = web_cfg['host'] port = web_cfg['port'] debug = web_cfg['debug'] logger.info("Web服务: %s:%d, debug=%s", host, port, debug) if debug: app.run(host=host, port=port, debug=True) else: try: from waitress import serve logger.info("使用 Waitress 生产服务器") try: serve(app, host=host, port=port, threads=4) except OSError: if port == 5001: logger.warning("端口 %d 被占用或无权限, 尝试端口 5002", port) serve(app, host=host, port=5002, threads=4) else: raise except ImportError: logger.warning("Waitress 未安装, 使用 Flask 开发服务器") app.run(host=host, port=port, debug=False) if __name__ == '__main__': main()