qwen_agent/routes/files.py
朱潮 77079539c1 refactor: remove file-parsing knowledge-base pipeline and Huey queue
The local file-parsing pipeline (upload -> Huey async parse -> generate
projects/data/.../document.txt) is no longer needed: RAG retrieval runs
against the backend vector store and does not read the local parse output,
so removing this has zero impact on existing bot Q&A.

- Delete task_queue/ (Huey queue, consumer, tasks, task status store)
- Delete parsing utils: dataset_manager, single_file_processor,
  data_merger, project_manager
- Delete db_manager.py (only managed task_status.db)
- routes/files.py: keep only POST /api/v1/upload; drop all
  parse/queue/task endpoints
- routes/projects.py: drop /tasks endpoint and task_status import
- utils/__init__.py & api_models.py: remove exports/models for deleted
  modules and queue task models
- start_unified.py & start_all_optimized.sh: no longer launch the
  queue consumer
- Drop huey dependency (keep redis)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:40:58 +08:00

96 lines
3.3 KiB
Python

import os
import uuid
import shutil
from datetime import datetime
from typing import Optional
from fastapi import APIRouter, HTTPException, UploadFile, File, Form
import logging
logger = logging.getLogger('app')
from utils.fastapi_utils import get_versioned_filename
router = APIRouter()
@router.post("/api/v1/upload")
async def upload_file(file: UploadFile = File(...), folder: Optional[str] = Form(None)):
"""
File upload API endpoint that uploads files to the ./projects/uploads/ directory.
You can specify a custom folder name. If omitted, a date-based folder is used.
When a folder is specified, the original filename is used and version control is supported.
Args:
file: Uploaded file
folder: Optional custom folder name
Returns:
dict: Response containing file path and folder information
"""
try:
# Debug information
logger.info(f"Received folder parameter: {folder}")
logger.info(f"File received: {file.filename if file else 'None'}")
# Determine the upload folder
if folder:
# Use the specified custom folder
target_folder = folder
target_folder = os.path.basename(target_folder)
else:
# Get the current date and format it as YYYYMMDD
current_date = datetime.now()
target_folder = current_date.strftime("%Y%m%d")
# Create upload directory
upload_dir = os.path.join("projects", "uploads", target_folder)
os.makedirs(upload_dir, exist_ok=True)
# Process filename
if not file.filename:
raise HTTPException(status_code=400, detail="Filename cannot be empty")
# Parse filename and extension
original_filename = file.filename
name_without_ext, file_extension = os.path.splitext(original_filename)
# Choose naming strategy based on whether a folder is specified
if folder:
final_filename, version = get_versioned_filename(upload_dir, name_without_ext, file_extension)
file_path = os.path.join(upload_dir, final_filename)
# Save file
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
return {
"success": True,
"message": f"File uploaded successfully{' (version: ' + str(version) + ')' if version > 1 else ''}",
"file_path": file_path,
"folder": target_folder,
"original_filename": original_filename,
"version": version
}
else:
# Use UUID unique filename (original logic)
unique_filename = f"{uuid.uuid4()}{file_extension}"
file_path = os.path.join(upload_dir, unique_filename)
# Save file
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
return {
"success": True,
"message": "File uploaded successfully",
"file_path": file_path,
"folder": target_folder,
"original_filename": original_filename
}
except HTTPException:
raise
except Exception as e:
logger.error(f"Error uploading file: {str(e)}")
raise HTTPException(status_code=500, detail=f"File upload failed: {str(e)}")