diff --git a/main.py b/main.py index bf18092..77d7112 100644 --- a/main.py +++ b/main.py @@ -15,13 +15,15 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse from pydantic import BaseModel, HttpUrl +# 只导入AI_Agent的统一入口方法(不再导入多个内部方法) from AI_Agent import generate_tender_from_input from config import DetectionResponse from process import detect_large_image_from_url -# 配置文件存储路径 -UPLOAD_DIR = Path("uploaded_files") -OUTPUT_DIR = Path("generated_tenders") +# 配置文件存储路径(使用绝对路径确保一致性) +BASE_DIR = Path(__file__).parent.resolve() # 项目根目录绝对路径 +UPLOAD_DIR = BASE_DIR / "uploaded_files" +OUTPUT_DIR = BASE_DIR / "generated_tenders" UPLOAD_DIR.mkdir(exist_ok=True) OUTPUT_DIR.mkdir(exist_ok=True) @@ -147,9 +149,11 @@ async def get_supported_types(): async def generate_tender_file(file: UploadFile = File(...)): """ 上传招标文件(Word格式),生成投标文件 + 支持的文件格式:.docx 返回生成文件的相对路径,用于下载接口 """ + # 初始化upload_path变量,避免UnboundLocalError upload_path = None # 验证文件类型 @@ -172,15 +176,16 @@ async def generate_tender_file(file: UploadFile = File(...)): print(f"已接收上传文件:{upload_path}") - # 生成输出文件名和路径 + # 生成输出文件名和路径(使用绝对路径) output_filename = f"投标文件_生成版_{timestamp}.docx" output_path = OUTPUT_DIR / output_filename + output_path_abs = str(output_path.resolve()) # 绝对路径 # 调用AI_Agent的统一入口方法(仅这一个调用) print("开始生成投标文件...") generate_success = generate_tender_from_input( - input_word_path=str(upload_path), - output_word_path=str(output_path) + input_word_path=str(upload_path.resolve()), # 传入绝对路径 + output_word_path=output_path_abs ) if not generate_success: @@ -193,10 +198,19 @@ async def generate_tender_file(file: UploadFile = File(...)): # 计算文件大小 file_size = output_path.stat().st_size - # 构建相对路径(相对于项目根目录) - relative_path = str(output_path.relative_to(Path.cwd())) + # 修复:使用os.path.relpath计算相对路径,更灵活 + try: + # 计算相对于项目根目录的相对路径 + relative_path = os.path.relpath(output_path_abs, str(BASE_DIR)) + # 统一路径分隔符为 '/',避免Windows和Linux差异 + relative_path = relative_path.replace(os.sep, '/') + except Exception as e: + # 异常情况下直接返回文件名(降级方案) + relative_path = output_filename + print(f"计算相对路径失败,使用降级方案:{e}") - print(f"投标文件生成成功:{output_path}") + print(f"投标文件生成成功:{output_path_abs}") + print(f"相对路径:{relative_path}") return { "status": "success", @@ -229,12 +243,17 @@ async def generate_tender_file(file: UploadFile = File(...)): async def download_generated_file(relative_path: str): """ 根据相对路径下载生成的投标文件 + Args: relative_path: 生成文件的相对路径(从/generate_tender接口获取) """ - # 解析绝对路径,防止路径穿越攻击 try: - abs_path = Path(relative_path).resolve() + # 修复:将相对路径转换为绝对路径 + # 统一路径分隔符 + relative_path = relative_path.replace('/', os.sep) + # 拼接项目根目录得到绝对路径 + abs_path = BASE_DIR / relative_path + abs_path = abs_path.resolve() # 解析完整路径 # 验证路径是否在允许的输出目录内 if not abs_path.is_relative_to(OUTPUT_DIR.resolve()): @@ -271,9 +290,16 @@ async def list_generated_files(): """列出所有生成的投标文件(可选接口)""" files = [] for file in OUTPUT_DIR.glob("*.docx"): + # 计算相对路径 + try: + relative_path = os.path.relpath(str(file.resolve()), str(BASE_DIR)) + relative_path = relative_path.replace(os.sep, '/') + except: + relative_path = file.name + files.append({ "file_name": file.name, - "relative_path": str(file.relative_to(Path.cwd())), + "relative_path": relative_path, "file_size": file.stat().st_size, "created_time": file.stat().st_ctime })