diff --git a/backend/build-docker-fixed.sh b/backend/build-docker-fixed.sh deleted file mode 100644 index f316619..0000000 --- a/backend/build-docker-fixed.sh +++ /dev/null @@ -1,369 +0,0 @@ -#!/bin/bash - -# 云盘应用 Docker 构建和部署脚本 (修复权限问题版本) -# 用于构建生产环境的 Docker 镜像并部署到 Linux 环境 - -set -e - -# 配置变量 -APP_NAME="cloud-drive-backend" -IMAGE_NAME="${APP_NAME}:latest" -CONTAINER_NAME="${APP_NAME}" -PORT="8002" -USE_SUDO=false - -# Docker命令包装函数 -docker_cmd() { - if [ "$USE_SUDO" = true ]; then - sudo docker "$@" - else - docker "$@" - fi -} - -# Docker Compose命令包装函数 -docker_compose_cmd() { - if [ "$USE_SUDO" = true ]; then - sudo docker-compose "$@" - else - docker-compose "$@" - fi -} - -# 颜色输出 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# 日志函数 -log_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# 检查 Docker 是否安装 -check_docker() { - if ! command -v docker &> /dev/null; then - log_error "Docker 未安装,请先安装 Docker" - exit 1 - fi - - # 检查Docker权限 - if ! docker info &> /dev/null; then - log_warning "Docker权限不足,尝试修复..." - - # 检查当前用户是否在docker组中 - if ! groups $(whoami) | grep -q docker; then - log_warning "当前用户不在docker组中" - - # 尝试将用户添加到docker组 - if command -v sudo &> /dev/null; then - log_info "尝试将用户添加到docker组(需要sudo权限)..." - sudo usermod -aG docker $(whoami) 2>/dev/null || { - log_warning "无法自动添加用户到docker组" - log_info "请手动执行: sudo usermod -aG docker $(whoami)" - log_info "然后重新登录或执行: newgrp docker" - } - else - log_error "sudo命令不可用,无法修复Docker权限" - fi - fi - - # 尝试使用sudo运行docker - if command -v sudo &> /dev/null && sudo docker info &> /dev/null; then - log_info "检测到可以使用sudo运行Docker" - USE_SUDO=true - else - log_error "Docker权限不足且无法修复" - log_info "解决方案:" - log_info "1. 将用户添加到docker组: sudo usermod -aG docker $(whoami)" - log_info "2. 重新登录或执行: newgrp docker" - log_info "3. 或使用sudo运行此脚本" - exit 1 - fi - fi - - log_success "Docker 已安装并可访问" -} - -# 检查 Docker Compose 是否安装 -check_docker_compose() { - if ! command -v docker-compose &> /dev/null; then - log_error "Docker Compose 未安装,请先安装 Docker Compose" - exit 1 - fi - log_success "Docker Compose 已安装" -} - -# 停止并删除现有容器 -stop_existing_container() { - if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then - log_warning "停止现有容器 ${CONTAINER_NAME}" - docker_cmd stop ${CONTAINER_NAME} - fi - - if docker_cmd ps -aq -f name=${CONTAINER_NAME} | grep -q .; then - log_warning "删除现有容器 ${CONTAINER_NAME}" - docker_cmd rm ${CONTAINER_NAME} - fi -} - -# 构建镜像 -build_image() { - log_info "开始构建 Docker 镜像..." - docker_cmd build -t ${IMAGE_NAME} . - - if [ $? -eq 0 ]; then - log_success "镜像构建成功: ${IMAGE_NAME}" - else - log_error "镜像构建失败" - exit 1 - fi -} - -# 运行容器 -run_container() { - log_info "启动容器..." - - # 创建必要的目录 - mkdir -p uploads logs - - docker_cmd run -d \ - --name ${CONTAINER_NAME} \ - --restart unless-stopped \ - -p ${PORT}:${PORT} \ - -v $(pwd)/uploads:/app/uploads \ - -v $(pwd)/logs:/app/logs \ - -e ENVIRONMENT=production \ - -e TZ=Asia/Shanghai \ - ${IMAGE_NAME} - - if [ $? -eq 0 ]; then - log_success "容器启动成功: ${CONTAINER_NAME}" - else - log_error "容器启动失败" - exit 1 - fi -} - -# 检查容器状态 -check_container() { - log_info "检查容器状态..." - sleep 5 - - if docker_cmd ps | grep -q ${CONTAINER_NAME}; then - log_success "容器运行正常" - - # 显示容器日志 - log_info "容器日志:" - docker_cmd logs ${CONTAINER_NAME} - - # 测试健康检查 - log_info "测试健康检查..." - sleep 10 - if curl -f http://localhost:${PORT}/api/v1/health &> /dev/null; then - log_success "健康检查通过!" - else - log_warning "健康检查失败,但容器仍在运行" - fi - else - log_error "容器未正常运行" - log_error "容器日志:" - docker_cmd logs ${CONTAINER_NAME} - exit 1 - fi -} - -# 使用 Docker Compose 部署 -deploy_with_compose() { - log_info "使用 Docker Compose 部署..." - - # 创建 .env 文件(如果不存在) - if [ ! -f .env ]; then - log_warning "创建 .env 文件,请根据实际情况修改配置" - cat > .env << EOF -# 数据库配置 -DATABASE_URL=mysql://username:password@mysql:3306/mytest_db -MYSQL_ROOT_PASSWORD=rootpassword -MYSQL_DATABASE=mytest_db -MYSQL_USER=username -MYSQL_PASSWORD=password - -# Redis 配置 -REDIS_URL=redis://redis:6379/0 - -# 应用配置 -SECRET_KEY=your-production-secret-key -CORS_ORIGINS=http://localhost:3003,https://yourdomain.com -ENVIRONMENT=production -EOF - log_warning "请编辑 .env 文件设置正确的配置" - fi - - docker_compose_cmd down - docker_compose_cmd up -d --build - - if [ $? -eq 0 ]; then - log_success "Docker Compose 部署成功" - log_info "等待服务启动..." - sleep 15 - - if curl -f http://localhost:${PORT}/api/v1/health &> /dev/null; then - log_success "应用启动成功!" - log_info "服务地址: http://localhost:${PORT}" - log_info "API文档: http://localhost:${PORT}/docs" - log_info "健康检查: http://localhost:${PORT}/api/v1/health" - else - log_warning "应用启动可能有问题,请检查日志" - log_info "查看日志命令: docker-compose logs -f" - docker_compose_cmd logs --tail=20 - fi - else - log_error "Docker Compose 部署失败" - exit 1 - fi -} - -# 清理镜像和容器 -cleanup() { - log_info "清理旧的镜像和容器..." - - # 停止并删除容器 - stop_existing_container - - # 删除镜像 - if docker_cmd images -q ${IMAGE_NAME} | grep -q .; then - log_warning "删除旧镜像: ${IMAGE_NAME}" - docker_cmd rmi ${IMAGE_NAME} 2>/dev/null || true - fi - - # 清理未使用的镜像和容器 - log_info "清理未使用的 Docker 资源..." - docker_cmd system prune -f - - log_success "清理完成" -} - -# 显示帮助信息 -show_help() { - echo "云盘应用 Docker 部署脚本 (权限修复版)" - echo "" - echo "用法: $0 [选项]" - echo "" - echo "选项:" - echo " build - 仅构建镜像" - echo " run - 仅运行容器(需要先构建镜像)" - echo " compose - 使用 Docker Compose 部署" - echo " stop - 停止容器" - echo " restart - 重启容器" - echo " logs - 查看容器日志" - echo " cleanup - 清理镜像和容器" - echo " status - 查看容器状态" - echo " help - 显示此帮助信息" - echo "" - echo "默认行为: 构建镜像并运行容器" - echo "" - echo "权限修复功能:" - echo "- 自动检测Docker权限" - echo "- 尝试自动修复权限问题" - echo "- 支持sudo模式运行Docker" -} - -# 主函数 -main() { - case "${1:-}" in - "build") - check_docker - build_image - ;; - "run") - check_docker - stop_existing_container - run_container - check_container - ;; - "compose") - check_docker - check_docker_compose - deploy_with_compose - ;; - "stop") - check_docker - if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then - docker_cmd stop ${CONTAINER_NAME} - log_success "容器已停止" - else - log_warning "容器未运行" - fi - ;; - "restart") - check_docker - if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then - docker_cmd restart ${CONTAINER_NAME} - log_success "容器已重启" - sleep 5 - check_container - else - log_warning "容器未运行,尝试启动..." - stop_existing_container - build_image - run_container - check_container - fi - ;; - "logs") - check_docker - if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then - docker_cmd logs -f ${CONTAINER_NAME} - else - log_warning "容器未运行" - fi - ;; - "cleanup") - check_docker - cleanup - ;; - "status") - check_docker - if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then - log_success "容器正在运行" - docker_cmd ps | grep ${CONTAINER_NAME} - else - log_warning "容器未运行" - fi - ;; - "help"|"-h"|"--help") - show_help - ;; - "") - log_info "开始构建和部署云盘应用..." - check_docker - stop_existing_container - build_image - run_container - check_container - log_success "部署完成!应用正在运行中" - ;; - *) - log_error "未知选项: $1" - show_help - exit 1 - ;; - esac -} - -# 执行主函数 -main "$@" \ No newline at end of file diff --git a/backend/build-docker.sh b/backend/build-docker.sh deleted file mode 100644 index 0c0c16c..0000000 --- a/backend/build-docker.sh +++ /dev/null @@ -1,360 +0,0 @@ -#!/bin/bash - -# 云盘应用 Docker 构建和部署脚本 -# 用于构建生产环境的 Docker 镜像并部署到 Linux 环境 - -set -e - -# 配置变量 -APP_NAME="cloud-drive-backend" -IMAGE_NAME="${APP_NAME}:latest" -CONTAINER_NAME="${APP_NAME}" -PORT="8002" -USE_SUDO=false - -# Docker命令包装函数 -docker_cmd() { - if [ "$USE_SUDO" = true ]; then - sudo docker "$@" - else - docker "$@" - fi -} - -# Docker Compose命令包装函数 -docker_compose_cmd() { - if [ "$USE_SUDO" = true ]; then - sudo docker-compose "$@" - else - docker-compose "$@" - fi -} - -# 颜色输出 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# 日志函数 -log_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# 检查 Docker 是否安装 -check_docker() { - if ! command -v docker &> /dev/null; then - log_error "Docker 未安装,请先安装 Docker" - exit 1 - fi - - # 检查Docker权限 - if ! docker info &> /dev/null; then - log_warning "Docker权限不足,尝试修复..." - - # 检查当前用户是否在docker组中 - if ! groups $(whoami) | grep -q docker; then - log_warning "当前用户不在docker组中" - - # 尝试将用户添加到docker组 - if command -v sudo &> /dev/null; then - log_info "尝试将用户添加到docker组(需要sudo权限)..." - sudo usermod -aG docker $(whoami) 2>/dev/null || { - log_warning "无法自动添加用户到docker组" - log_info "请手动执行: sudo usermod -aG docker $(whoami)" - log_info "然后重新登录或执行: newgrp docker" - } - else - log_error "sudo命令不可用,无法修复Docker权限" - fi - fi - - # 尝试使用sudo运行docker - if command -v sudo &> /dev/null && sudo docker info &> /dev/null; then - log_info "检测到可以使用sudo运行Docker" - USE_SUDO=true - else - log_error "Docker权限不足且无法修复" - log_info "解决方案:" - log_info "1. 将用户添加到docker组: sudo usermod -aG docker $(whoami)" - log_info "2. 重新登录或执行: newgrp docker" - log_info "3. 或使用sudo运行此脚本" - exit 1 - fi - fi - - log_success "Docker 已安装并可访问" -} - -# 检查 Docker Compose 是否安装 -check_docker_compose() { - if ! command -v docker-compose &> /dev/null; then - log_error "Docker Compose 未安装,请先安装 Docker Compose" - exit 1 - fi - log_success "Docker Compose 已安装" -} - -# 停止并删除现有容器 -stop_existing_container() { - if docker_cmd ps -q -f name=${CONTAINER_NAME} | grep -q .; then - log_warning "停止现有容器 ${CONTAINER_NAME}" - docker_cmd stop ${CONTAINER_NAME} - fi - - if docker_cmd ps -aq -f name=${CONTAINER_NAME} | grep -q .; then - log_warning "删除现有容器 ${CONTAINER_NAME}" - docker_cmd rm ${CONTAINER_NAME} - fi -} - -# 构建镜像 -build_image() { - log_info "开始构建 Docker 镜像..." - docker_cmd build -t ${IMAGE_NAME} . - - if [ $? -eq 0 ]; then - log_success "镜像构建成功: ${IMAGE_NAME}" - else - log_error "镜像构建失败" - exit 1 - fi -} - -# 运行容器 -run_container() { - log_info "启动容器..." - - # 创建必要的目录 - mkdir -p uploads logs - - docker_cmd run -d \ - --name ${CONTAINER_NAME} \ - --restart unless-stopped \ - -p ${PORT}:${PORT} \ - -v $(pwd)/uploads:/app/uploads \ - -v $(pwd)/logs:/app/logs \ - -e ENVIRONMENT=production \ - -e TZ=Asia/Shanghai \ - ${IMAGE_NAME} - - if [ $? -eq 0 ]; then - log_success "容器启动成功: ${CONTAINER_NAME}" - else - log_error "容器启动失败" - exit 1 - fi -} - -# 检查容器状态 -check_container() { - log_info "检查容器状态..." - sleep 5 - - if docker_cmd ps | grep -q ${CONTAINER_NAME}; then - log_success "容器运行正常" - - # 显示容器日志 - log_info "容器日志:" - docker_cmd logs ${CONTAINER_NAME} - - # 测试健康检查 - log_info "测试健康检查..." - sleep 10 - if curl -f http://localhost:${PORT}/api/v1/health &> /dev/null; then - log_success "健康检查通过!" - else - log_warning "健康检查失败,但容器仍在运行" - fi - else - log_error "容器未正常运行" - log_error "容器日志:" - docker_cmd logs ${CONTAINER_NAME} - exit 1 - fi -} - -# 使用 Docker Compose 部署 -deploy_with_compose() { - log_info "使用 Docker Compose 部署..." - - # 创建 .env 文件(如果不存在) - if [ ! -f .env ]; then - log_warning "创建 .env 文件,请根据实际情况修改配置" - cat > .env << EOF -# 数据库配置 -DATABASE_URL=mysql://username:password@mysql:3306/mytest_db -MYSQL_ROOT_PASSWORD=rootpassword -MYSQL_DATABASE=mytest_db -MYSQL_USER=username -MYSQL_PASSWORD=password - -# Redis 配置 -REDIS_URL=redis://redis:6379/0 - -# 应用配置 -SECRET_KEY=your-production-secret-key -CORS_ORIGINS=http://localhost:3003,https://yourdomain.com -ENVIRONMENT=production -EOF - log_warning "请编辑 .env 文件设置正确的配置" - fi - - docker_compose_cmd down - docker_compose_cmd up -d --build - - if [ $? -eq 0 ]; then - log_success "Docker Compose 部署成功" - log_info "等待服务启动..." - sleep 15 - - if curl -f http://localhost:${PORT}/api/v1/health &> /dev/null; then - log_success "应用启动成功!" - log_info "服务地址: http://localhost:${PORT}" - log_info "API文档: http://localhost:${PORT}/docs" - log_info "健康检查: http://localhost:${PORT}/api/v1/health" - else - log_warning "应用启动可能有问题,请检查日志" - log_info "查看日志命令: docker-compose logs -f" - docker_compose_cmd logs --tail=20 - fi - else - log_error "Docker Compose 部署失败" - exit 1 - fi -} - -# 清理镜像和容器 -cleanup() { - log_info "清理旧的镜像和容器..." - - # 停止并删除容器 - stop_existing_container - - # 删除镜像 - if docker_cmd images -q ${IMAGE_NAME} | grep -q .; then - log_warning "删除旧镜像: ${IMAGE_NAME}" - docker_cmd rmi ${IMAGE_NAME} 2>/dev/null || true - fi - - # 清理未使用的镜像和容器 - log_info "清理未使用的 Docker 资源..." - docker_cmd system prune -f - - log_success "清理完成" -} - -# 显示帮助信息 -show_help() { - echo "云盘应用 Docker 部署脚本" - echo "" - echo "用法: $0 [选项]" - echo "" - echo "选项:" - echo " build - 仅构建镜像" - echo " run - 仅运行容器(需要先构建镜像)" - echo " compose - 使用 Docker Compose 部署" - echo " stop - 停止容器" - echo " restart - 重启容器" - echo " logs - 查看容器日志" - echo " cleanup - 清理镜像和容器" - echo " status - 查看容器状态" - echo " help - 显示此帮助信息" - echo "" - echo "默认行为: 构建镜像并运行容器" -} - -# 主函数 -main() { - case "${1:-}" in - "build") - check_docker - build_image - ;; - "run") - check_docker - stop_existing_container - run_container - check_container - ;; - "compose") - check_docker - check_docker_compose - deploy_with_compose - ;; - "stop") - if docker ps -q -f name=${CONTAINER_NAME} | grep -q .; then - docker stop ${CONTAINER_NAME} - log_success "容器已停止" - else - log_warning "容器未运行" - fi - ;; - "restart") - if docker ps -q -f name=${CONTAINER_NAME} | grep -q .; then - docker restart ${CONTAINER_NAME} - log_success "容器已重启" - sleep 5 - check_container - else - log_warning "容器未运行,尝试启动..." - check_docker - stop_existing_container - run_container - check_container - fi - ;; - "logs") - if docker ps -q -f name=${CONTAINER_NAME} | grep -q .; then - docker logs -f ${CONTAINER_NAME} - else - log_warning "容器未运行" - fi - ;; - "cleanup") - check_docker - cleanup - ;; - "status") - if docker ps -q -f name=${CONTAINER_NAME} | grep -q .; then - log_success "容器正在运行" - docker ps | grep ${CONTAINER_NAME} - else - log_warning "容器未运行" - fi - ;; - "help"|"-h"|"--help") - show_help - ;; - "") - log_info "开始构建和部署云盘应用..." - check_docker - stop_existing_container - build_image - run_container - check_container - log_success "部署完成!应用正在运行中" - ;; - *) - log_error "未知选项: $1" - show_help - exit 1 - ;; - esac -} - -# 执行主函数 -main "$@" \ No newline at end of file diff --git a/backend/build.py b/backend/build.py deleted file mode 100644 index ec8cee9..0000000 --- a/backend/build.py +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env python3 -""" -云盘应用打包脚本 -用于将FastAPI应用打包为可执行文件 -""" - -import os -import sys -import shutil -from pathlib import Path - -def clean_build(): - """清理之前的构建文件""" - print("清理之前的构建文件...") - - # 清理PyInstaller生成的文件 - dirs_to_clean = ['build', 'dist', '__pycache__'] - for dir_name in dirs_to_clean: - if os.path.exists(dir_name): - shutil.rmtree(dir_name) - print(f" ✅ 已删除: {dir_name}") - - # 清理.spec文件 - if os.path.exists('main.spec'): - os.remove('main.spec') - print(f" ✅ 已删除: main.spec") - -def check_dependencies(): - """检查依赖是否安装""" - print("📦 检查依赖...") - - required_packages = ['fastapi', 'uvicorn', 'pydantic', 'sqlalchemy', 'loguru'] - missing_packages = [] - - for package in required_packages: - try: - __import__(package) - print(f" ✅ {package}") - except ImportError: - missing_packages.append(package) - print(f" ❌ {package} (缺失)") - - if missing_packages: - print(f"\n❌ 缺少以下依赖: {', '.join(missing_packages)}") - print("请运行: pip install -r requirements.txt") - return False - - print("✅ 所有依赖都已安装") - return True - -def build_executable(): - """构建可执行文件""" - print("🔨 开始构建可执行文件...") - - # 使用自定义的spec文件进行构建 - import subprocess - result = subprocess.run([ - sys.executable, '-m', 'PyInstaller', - 'build.spec', - '--clean', - '--noconfirm' - ], capture_output=True, text=True) - - if result.returncode == 0: - print("✅ 构建成功!") - print(f"📁 可执行文件位置: {os.path.abspath('dist/cloud-drive-server.exe')}") - return True - else: - print("❌ 构建失败!") - print("错误信息:") - print(result.stderr) - return False - -def create_deployment_package(): - """创建部署包""" - print("📦 创建部署包...") - - dist_dir = Path('dist') - deploy_dir = Path('deploy') - - # 创建部署目录 - if deploy_dir.exists(): - shutil.rmtree(deploy_dir) - deploy_dir.mkdir() - - # 复制可执行文件 - exe_path = dist_dir / 'cloud-drive-server.exe' - if exe_path.exists(): - shutil.copy2(exe_path, deploy_dir / 'cloud-drive-server.exe') - print(" ✅ 复制可执行文件") - - # 复制配置文件 - config_files = ['requirements.txt', '.env.example'] - for config_file in config_files: - if os.path.exists(config_file): - shutil.copy2(config_file, deploy_dir / config_file) - print(f" ✅ 复制配置文件: {config_file}") - - # 创建启动脚本 - start_script = deploy_dir / 'start.bat' - with open(start_script, 'w', encoding='utf-8') as f: - f.write("""@echo off -echo 🚀 启动云盘服务器... -echo 📝 确保MySQL和Redis服务已启动 -echo. -cloud-drive-server.exe -pause -""") - print(" ✅ 创建启动脚本: start.bat") - - # 创建README - readme_path = deploy_dir / 'README.md' - with open(readme_path, 'w', encoding='utf-8') as f: - f.write("""# 云盘应用部署包 - -## 快速启动 - -1. **确保数据库和缓存服务运行** - - MySQL服务器已启动 - - Redis服务器已启动(可选) - -2. **配置环境变量** - - 复制 `.env.example` 为 `.env` - - 修改 `.env` 中的数据库连接信息 - -3. **启动应用** - - Windows: 双击 `start.bat` 或运行 `cloud-drive-server.exe` - - 访问 http://localhost:8000 - -## 配置说明 - -在 `.env` 文件中配置以下参数: - -```env -# 数据库配置 -DATABASE_URL=mysql+pymysql://username:password@localhost:3306/database_name - -# JWT密钥 -SECRET_KEY=your-secret-key-here - -# 其他配置... -``` - -## API文档 - -启动后访问: -- Swagger UI: http://localhost:8000/docs -- ReDoc: http://localhost:8000/redoc - -## 故障排除 - -1. **端口被占用**: 修改 `.env` 中的 `PORT` 配置 -2. **数据库连接失败**: 检查MySQL服务状态和连接配置 -3. **缺少依赖**: 确保所有依赖已正确安装 -""") - print(" ✅ 创建README文档") - - print(f"📁 部署包位置: {deploy_dir.absolute()}") - return True - -def main(): - """主函数""" - print("🏗️ 云盘应用打包工具") - print("=" * 50) - - # 1. 检查依赖 - if not check_dependencies(): - sys.exit(1) - - # 2. 清理之前的构建 - clean_build() - - # 3. 构建可执行文件 - if not build_executable(): - sys.exit(1) - - # 4. 创建部署包 - if not create_deployment_package(): - sys.exit(1) - - print("\n🎉 打包完成!") - print("📁 部署包位于 'deploy' 目录") - print("🚀 可以将整个 deploy 文件夹复制到目标服务器运行") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/backend/build_linux.bat b/backend/build_linux.bat deleted file mode 100644 index d1f6b29..0000000 --- a/backend/build_linux.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -echo 正在为Linux打包Python程序... -docker run --rm -v "%cd%:/src" cdrx/pyinstaller-linux:python3-20231002 "pyinstaller --onefile main.py" -echo 打包完成!检查 dist/ 目录 \ No newline at end of file diff --git a/backend/build_linux.py b/backend/build_linux.py deleted file mode 100644 index dd4c8ac..0000000 --- a/backend/build_linux.py +++ /dev/null @@ -1,332 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -云盘后端Linux打包脚本 -使用PyInstaller将后端应用打包成Linux可执行文件 -""" - -import os -import sys -import shutil -import subprocess -from pathlib import Path -import argparse - -def check_python_version(): - """检查Python版本""" - if sys.version_info < (3, 8): - print("错误: 需要Python 3.8或更高版本") - sys.exit(1) - print(f"[OK] Python版本: {sys.version}") - -def check_dependencies(): - """检查必要的依赖""" - try: - import PyInstaller - print(f"[OK] PyInstaller版本: {PyInstaller.__version__}") - except ImportError: - print("错误: 未安装PyInstaller") - print("请运行: pip install pyinstaller") - sys.exit(1) - -def clean_build_dirs(): - """清理之前的构建目录""" - dirs_to_clean = ['build', 'dist', '__pycache__'] - for dir_name in dirs_to_clean: - if os.path.exists(dir_name): - print(f"清理目录: {dir_name}") - shutil.rmtree(dir_name) - - # 清理Python缓存文件 - for root, dirs, files in os.walk('.'): - for file in files: - if file.endswith('.pyc') or file.endswith('.pyo'): - os.remove(os.path.join(root, file)) - if '__pycache__' in dirs: - shutil.rmtree(os.path.join(root, '__pycache__')) - -def create_spec_file(): - """创建或更新PyInstaller规格文件""" - # 直接使用现有的build.spec文件 - print("[OK] build.spec 文件已存在,跳过创建") - -def run_pyinstaller(): - """运行PyInstaller进行打包""" - print("开始打包...") - try: - # 使用spec文件进行打包 - cmd = ['pyinstaller', '--clean', 'build.spec'] - result = subprocess.run(cmd, check=True, capture_output=True, text=True) - print("[OK] PyInstaller执行成功") - if result.stdout: - print("输出:", result.stdout) - except subprocess.CalledProcessError as e: - print(f"错误: PyInstaller执行失败: {e}") - if e.stderr: - print("错误输出:", e.stderr) - sys.exit(1) - -def create_deployment_package(): - """创建部署包""" - dist_dir = Path('dist') - deploy_dir = Path('deploy') - - if deploy_dir.exists(): - shutil.rmtree(deploy_dir) - - deploy_dir.mkdir() - - # 复制可执行文件 - exe_file = dist_dir / 'cloud-drive-server' - if exe_file.exists(): - shutil.copy2(exe_file, deploy_dir) - print(f"[OK] 复制可执行文件到 {deploy_dir}") - - # 复制配置文件 - config_files = ['.env.example'] - for config_file in config_files: - if os.path.exists(config_file): - shutil.copy2(config_file, deploy_dir) - print(f"[OK] 复制配置文件 {config_file}") - - # 复制安装脚本 - install_scripts = ['install.sh', 'install_user.sh'] - for script in install_scripts: - if os.path.exists(script): - shutil.copy2(script, deploy_dir) - os.chmod(deploy_dir / script, 0o755) - print(f"[OK] 复制安装脚本 {script}") - - # 创建部署目录结构 - (deploy_dir / 'logs').mkdir(exist_ok=True) - (deploy_dir / 'uploads').mkdir(exist_ok=True) - - # 创建启动脚本 - create_startup_script(deploy_dir) - - # 创建README - create_readme(deploy_dir) - - print(f"[OK] 部署包创建完成: {deploy_dir.absolute()}") - - deploy_dir.mkdir() - - # 复制可执行文件 - exe_file = dist_dir / 'cloud-drive-server' - if exe_file.exists(): - shutil.copy2(exe_file, deploy_dir) - print(f"[OK] 复制可执行文件到 {deploy_dir}") - - # 复制配置文件 - config_files = ['.env.example'] - for config_file in config_files: - if os.path.exists(config_file): - shutil.copy2(config_file, deploy_dir) - print(f"[OK] 复制配置文件 {config_file}") - - # 创建部署目录结构 - (deploy_dir / 'logs').mkdir(exist_ok=True) - (deploy_dir / 'uploads').mkdir(exist_ok=True) - - # 创建启动脚本 - create_startup_script(deploy_dir) - - # 创建README - create_readme(deploy_dir) - - print(f"[OK] 部署包创建完成: {deploy_dir.absolute()}") - -def create_startup_script(deploy_dir): - """创建启动脚本""" - # Linux启动脚本 - startup_script = '''#!/bin/bash -# 云盘后端服务启动脚本 - -# 设置环境变量 -export PYTHONPATH=${PYTHONPATH}:$(dirname "$0") - -# 进入脚本所在目录 -cd "$(dirname "$0")" - -# 检查环境文件 -if [ ! -f ".env" ]; then - echo "警告: .env 文件不存在,将使用默认配置" - if [ -f ".env.example" ]; then - cp .env.example .env - echo "已复制 .env.example 为 .env,请根据需要修改配置" - fi -fi - -# 创建必要的目录 -mkdir -p logs uploads - -# 启动服务 -echo "启动云盘后端服务..." -./cloud-drive-server -''' - - script_path = deploy_dir / 'start.sh' - with open(script_path, 'w', encoding='utf-8') as f: - f.write(startup_script) - - # 设置执行权限 - os.chmod(script_path, 0o755) - print("[OK] 创建启动脚本 start.sh") - -def create_readme(deploy_dir): - """创建部署说明文档""" - readme_content = '''# 云盘后端服务部署说明 - -## 文件说明 - -- `cloud-drive-server`: 主程序可执行文件 -- `start.sh`: 启动脚本 -- `.env.example`: 环境配置示例文件 - -## 快速开始 - -1. **配置环境变量** - ```bash - cp .env.example .env - # 编辑 .env 文件,配置数据库和Redis连接信息 - nano .env - ``` - -2. **启动服务** - ```bash - chmod +x start.sh - ./start.sh - ``` - - 或者直接运行: - ```bash - ./cloud-drive-server - ``` - -3. **访问服务** - - API文档: http://localhost:8000/docs - - 健康检查: http://localhost:8000/api/v1/health - -## 环境配置 - -主要配置项(.env文件): - -```env -# 数据库配置 -DATABASE_URL=mysql+pymysql://用户名:密码@主机:端口/数据库名 - -# Redis配置 -REDIS_URL=redis://主机:端口 - -# JWT配置 -JWT_SECRET_KEY=你的密钥 -JWT_EXPIRE_MINUTES=30 - -# 文件上传配置 -UPLOAD_DIR=uploads -MAX_FILE_SIZE=10485760 # 10MB -``` - -## 系统要求 - -- Linux 64位系统 -- MySQL 5.7+ 或 8.0+ -- Redis (可选) -- 至少512MB内存 -- 至少100MB磁盘空间 - -## 日志 - -日志文件位置:`logs/app.log` - -## 问题排查 - -1. **端口占用** - - 默认端口8000,如需修改请编辑.env文件 - -2. **数据库连接失败** - - 检查DATABASE_URL配置 - - 确保数据库服务正在运行 - - 检查防火墙设置 - -3. **权限问题** - - 确保程序有执行权限:`chmod +x cloud-drive-server` - - 确保有写入logs和uploads目录的权限 - -## 后台运行 - -使用systemd或supervisor管理服务进程: - -### systemd 配置示例 - -创建服务文件 `/etc/systemd/system/cloud-drive.service`: - -```ini -[Unit] -Description=Cloud Drive Backend Service -After=network.target - -[Service] -Type=simple -User=www-data -WorkingDirectory=/path/to/deploy/directory -ExecStart=/path/to/deploy/directory/cloud-drive-server -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target -``` - -启用和启动服务: -```bash -sudo systemctl daemon-reload -sudo systemctl enable cloud-drive -sudo systemctl start cloud-drive -``` -''' - - readme_path = deploy_dir / 'README.md' - with open(readme_path, 'w', encoding='utf-8') as f: - f.write(readme_content) - print("[OK] 创建部署说明文档 README.md") - -def main(): - """主函数""" - parser = argparse.ArgumentParser(description='云盘后端Linux打包工具') - parser.add_argument('--clean', action='store_true', help='仅清理构建目录') - parser.add_argument('--no-clean', action='store_true', help='跳过清理步骤') - - args = parser.parse_args() - - print("=== 云盘后端Linux打包工具 ===") - print(f"当前目录: {os.getcwd()}") - - # 检查环境 - check_python_version() - check_dependencies() - - # 清理构建目录 - if args.clean: - clean_build_dirs() - print("[OK] 清理完成") - return - - if not args.no_clean: - clean_build_dirs() - - # 创建规格文件 - create_spec_file() - - # 运行打包 - run_pyinstaller() - - # 创建部署包 - create_deployment_package() - - print("\n=== 打包完成 ===") - print("部署包位置: ./deploy/") - print("请查看 ./deploy/README.md 了解部署说明") - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/backend/build_linux_fixed.py b/backend/build_linux_fixed.py deleted file mode 100644 index 8d37462..0000000 --- a/backend/build_linux_fixed.py +++ /dev/null @@ -1,312 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -云盘后端Linux打包脚本 -使用PyInstaller将后端应用打包成Linux可执行文件 -""" - -import os -import sys -import shutil -import subprocess -from pathlib import Path -import argparse - -def check_python_version(): - """检查Python版本""" - if sys.version_info < (3, 8): - print("错误: 需要Python 3.8或更高版本") - sys.exit(1) - print(f"[OK] Python版本: {sys.version}") - -def check_dependencies(): - """检查必要的依赖""" - try: - import PyInstaller - print(f"[OK] PyInstaller版本: {PyInstaller.__version__}") - except ImportError: - print("错误: 未安装PyInstaller") - print("请运行: pip install pyinstaller") - sys.exit(1) - -def clean_build_dirs(): - """清理之前的构建目录""" - dirs_to_clean = ['build', 'dist', '__pycache__'] - for dir_name in dirs_to_clean: - if os.path.exists(dir_name): - print(f"清理目录: {dir_name}") - shutil.rmtree(dir_name) - - # 清理Python缓存文件 - for root, dirs, files in os.walk('.'): - for file in files: - if file.endswith('.pyc') or file.endswith('.pyo'): - os.remove(os.path.join(root, file)) - if '__pycache__' in dirs: - shutil.rmtree(os.path.join(root, '__pycache__')) - -def create_spec_file(): - """创建或更新PyInstaller规格文件""" - # 直接使用现有的build.spec文件 - print("[OK] build.spec 文件已存在,跳过创建") - -def run_pyinstaller(): - """运行PyInstaller进行打包""" - print("开始打包...") - try: - # 使用spec文件进行打包 - cmd = ['pyinstaller', '--clean', 'build.spec'] - result = subprocess.run(cmd, check=True, capture_output=True, text=True) - print("[OK] PyInstaller执行成功") - if result.stdout: - print("输出:", result.stdout) - except subprocess.CalledProcessError as e: - print(f"错误: PyInstaller执行失败: {e}") - if e.stderr: - print("错误输出:", e.stderr) - sys.exit(1) - -def create_deployment_package(): - """创建部署包""" - dist_dir = Path('dist') - deploy_dir = Path('deploy') - - if deploy_dir.exists(): - shutil.rmtree(deploy_dir) - - deploy_dir.mkdir() - - # 复制可执行文件 - exe_file = dist_dir / 'cloud-drive-server' - if exe_file.exists(): - shutil.copy2(exe_file, deploy_dir) - print(f"[OK] 复制可执行文件到 {deploy_dir}") - - # 复制配置文件 - config_files = ['.env.example'] - for config_file in config_files: - if os.path.exists(config_file): - shutil.copy2(config_file, deploy_dir) - print(f"[OK] 复制配置文件 {config_file}") - - # 复制安装脚本 - install_scripts = ['install.sh', 'install_user.sh'] - for script in install_scripts: - if os.path.exists(script): - shutil.copy2(script, deploy_dir) - os.chmod(deploy_dir / script, 0o755) - print(f"[OK] 复制安装脚本 {script}") - - # 创建部署目录结构 - (deploy_dir / 'logs').mkdir(exist_ok=True) - (deploy_dir / 'uploads').mkdir(exist_ok=True) - - # 创建启动脚本 - create_startup_script(deploy_dir) - - # 创建README - create_readme(deploy_dir) - - print(f"[OK] 部署包创建完成: {deploy_dir.absolute()}") - -def create_startup_script(deploy_dir): - """创建启动脚本""" - # Linux启动脚本 - startup_script = '''#!/bin/bash -# 云盘后端服务启动脚本 - -# 设置环境变量 -export PYTHONPATH=${PYTHONPATH}:$(dirname "$0") - -# 进入脚本所在目录 -cd "$(dirname "$0")" - -# 检查环境文件 -if [ ! -f ".env" ]; then - echo "警告: .env 文件不存在,将使用默认配置" - if [ -f ".env.example" ]; then - cp .env.example .env - echo "已复制 .env.example 为 .env,请根据需要修改配置" - fi -fi - -# 创建必要的目录 -mkdir -p logs uploads - -# 启动服务 -echo "启动云盘后端服务..." -./cloud-drive-server -''' - - script_path = deploy_dir / 'start.sh' - with open(script_path, 'w', encoding='utf-8') as f: - f.write(startup_script) - - # 设置执行权限 - os.chmod(script_path, 0o755) - print("[OK] 创建启动脚本 start.sh") - -def create_readme(deploy_dir): - """创建部署说明文档""" - readme_content = '''# 云盘后端服务部署说明 - -## 文件说明 - -- `cloud-drive-server`: 主程序可执行文件 -- `start.sh`: 启动脚本 -- `install.sh`: 系统级安装脚本(需要sudo权限) -- `install_user.sh`: 用户级安装脚本(无需sudo权限) -- `.env.example`: 环境配置示例文件 - -## 快速开始 - -### 方法一:用户级安装(推荐,无需sudo权限) - -```bash -# 1. 运行用户级安装脚本 -./install_user.sh - -# 2. 配置环境变量 -cd ~/cloud-drive -cp .env.example .env -nano .env # 编辑配置文件 - -# 3. 启动服务 -./start.sh - -# 4. 查看状态 -./status.sh -``` - -### 方法二:系统级安装(需要sudo权限) - -```bash -# 1. 运行系统级安装脚本 -sudo ./install.sh - -# 2. 启动服务 -sudo systemctl start cloud-drive - -# 3. 查看状态 -sudo systemctl status cloud-drive -``` - -### 方法三:直接运行 - -```bash -# 1. 配置环境变量 -cp .env.example .env -nano .env # 编辑配置文件 - -# 2. 启动服务 -chmod +x cloud-drive-server -./cloud-drive-server -``` - -## 环境配置 - -主要配置项(.env文件): - -```env -# 数据库配置 -DATABASE_URL=mysql+pymysql://用户名:密码@主机:端口/数据库名 - -# Redis配置 -REDIS_URL=redis://主机:端口 - -# JWT配置 -JWT_SECRET_KEY=你的密钥 -JWT_EXPIRE_MINUTES=30 - -# 文件上传配置 -UPLOAD_DIR=uploads -MAX_FILE_SIZE=10485760 # 10MB -``` - -## 访问服务 - -- API文档: http://localhost:8000/docs -- 健康检查: http://localhost:8000/api/v1/health -- 根路径: http://localhost:8000/ - -## 系统要求 - -- Linux 64位系统 -- MySQL 5.7+ 或 8.0+ -- Redis (可选) -- 至少512MB内存 -- 至少100MB磁盘空间 - -## 问题排查 - -1. **端口占用** - - 默认端口8000,如需修改请编辑.env文件 - -2. **数据库连接失败** - - 检查DATABASE_URL配置 - - 确保数据库服务正在运行 - -3. **权限问题** - - 确保程序有执行权限:`chmod +x cloud-drive-server` - - 确保有写入logs和uploads目录的权限 - -4. **依赖缺失** - - 如果出现模块缺失错误,请确保打包包含了所有依赖 - - 可以尝试重新运行打包脚本 - -## 日志 - -日志文件位置: -- 用户级安装:`~/.local/share/cloud-drive/logs/app.log` -- 系统级安装:`/opt/cloud-drive/logs/app.log` -- 直接运行:`./logs/app.log` -''' - - readme_path = deploy_dir / 'README.md' - with open(readme_path, 'w', encoding='utf-8') as f: - f.write(readme_content) - print("[OK] 创建部署说明文档 README.md") - -def main(): - """主函数""" - parser = argparse.ArgumentParser(description='云盘后端Linux打包工具') - parser.add_argument('--clean', action='store_true', help='仅清理构建目录') - parser.add_argument('--no-clean', action='store_true', help='跳过清理步骤') - - args = parser.parse_args() - - print("=== 云盘后端Linux打包工具 ===") - print(f"当前目录: {os.getcwd()}") - - # 检查环境 - check_python_version() - check_dependencies() - - # 清理构建目录 - if args.clean: - clean_build_dirs() - print("[OK] 清理完成") - return - - if not args.no_clean: - clean_build_dirs() - - # 创建规格文件 - create_spec_file() - - # 运行打包 - run_pyinstaller() - - # 创建部署包 - create_deployment_package() - - print("\n=== 打包完成 ===") - print("部署包位置: ./deploy/") - print("请查看 ./deploy/README.md 了解部署说明") - print("\n安装方式:") - print("1. 用户级安装(推荐):./install_user.sh") - print("2. 系统级安装:sudo ./install.sh") - print("3. 直接运行:./cloud-drive-server") - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/backend/build_noshared.py b/backend/build_noshared.py deleted file mode 100644 index fca445f..0000000 --- a/backend/build_noshared.py +++ /dev/null @@ -1,242 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -适用于无共享库Python环境的打包脚本 -""" - -import os -import sys -import shutil -import subprocess -from pathlib import Path -import argparse - -def check_python_version(): - """检查Python版本""" - if sys.version_info < (3, 8): - print("错误: 需要Python 3.8或更高版本") - sys.exit(1) - print(f"[OK] Python版本: {sys.version}") - -def check_dependencies(): - """检查必要的依赖""" - try: - import PyInstaller - print(f"[OK] PyInstaller版本: {PyInstaller.__version__}") - except ImportError: - print("错误: 未安装PyInstaller") - print("请运行: pip install pyinstaller") - sys.exit(1) - -def clean_build_dirs(): - """清理之前的构建目录""" - dirs_to_clean = ['build', 'dist', '__pycache__'] - for dir_name in dirs_to_clean: - if os.path.exists(dir_name): - print(f"清理目录: {dir_name}") - shutil.rmtree(dir_name) - - # 清理Python缓存文件 - for root, dirs, files in os.walk('.'): - for file in files: - if file.endswith('.pyc') or file.endswith('.pyo'): - os.remove(os.path.join(root, file)) - if '__pycache__' in dirs: - shutil.rmtree(os.path.join(root, '__pycache__')) - -def run_pyinstaller_noshared(): - """运行PyInstaller进行打包(无共享库版本)""" - print("开始打包(无共享库模式)...") - - # 尝试多种打包方式 - spec_files = ['build_noshared.spec', 'build.spec'] - - for spec_file in spec_files: - if os.path.exists(spec_file): - print(f"使用规格文件: {spec_file}") - - # 构建命令 - cmd = ['pyinstaller', '--clean', '--noupx', spec_file] - - # 如果是build.spec,添加额外参数 - if spec_file == 'build.spec': - cmd.extend(['--noupx', '--debug', 'imports']) - - try: - result = subprocess.run(cmd, check=True, capture_output=True, text=True) - print(f"[OK] PyInstaller执行成功 (使用 {spec_file})") - if result.stdout: - print("输出:", result.stdout) - return True - except subprocess.CalledProcessError as e: - print(f"使用 {spec_file} 打包失败: {e}") - if e.stderr: - print("错误输出:", e.stderr) - continue - - print("错误: 所有打包方式都失败了") - return False - -def create_simple_package(): - """创建简单的部署包(不使用PyInstaller)""" - print("创建简单部署包...") - - deploy_dir = Path('deploy') - if deploy_dir.exists(): - shutil.rmtree(deploy_dir) - - deploy_dir.mkdir() - - # 复制源代码 - shutil.copytree('app', deploy_dir / 'app') - shutil.copy2('main.py', deploy_dir) - shutil.copy2('requirements.txt', deploy_dir) - shutil.copy2('.env.example', deploy_dir) - - # 创建启动脚本 - startup_script = '''#!/bin/bash -# 云盘后端服务启动脚本(Python模式) - -# 进入脚本所在目录 -cd "$(dirname "$0")" - -# 检查Python环境 -if ! command -v python3 &> /dev/null; then - echo "错误: 未找到python3" - exit 1 -fi - -# 检查虚拟环境 -if [ ! -d "venv" ]; then - echo "创建虚拟环境..." - python3 -m venv venv - source venv/bin/activate - pip install -r requirements.txt -else - echo "激活虚拟环境..." - source venv/bin/activate -fi - -# 检查环境文件 -if [ ! -f ".env" ]; then - echo "警告: .env 文件不存在,将使用默认配置" - if [ -f ".env.example" ]; then - cp .env.example .env - echo "已复制 .env.example 为 .env,请根据需要修改配置" - fi -fi - -# 启动服务 -echo "启动云盘后端服务..." -python main.py -''' - - script_path = deploy_dir / 'start.sh' - with open(script_path, 'w', encoding='utf-8') as f: - f.write(startup_script) - - os.chmod(script_path, 0o755) - - # 创建安装脚本 - install_script = '''#!/bin/bash -# 简单安装脚本 - -INSTALL_DIR="$HOME/cloud-drive" - -echo "=== 云盘后端服务安装(简单版本) ===" - -# 创建安装目录 -mkdir -p "$INSTALL_DIR" - -# 复制文件 -cp -r * "$INSTALL_DIR/" -cd "$INSTALL_DIR" - -# 设置权限 -chmod +x start.sh - -echo "=== 安装完成 ===" -echo "进入目录: cd $INSTALL_DIR" -echo "启动服务: ./start.sh" -''' - - install_path = deploy_dir / 'install_simple.sh' - with open(install_path, 'w', encoding='utf-8') as f: - f.write(install_script) - - os.chmod(install_path, 0o755) - - print(f"[OK] 简单部署包创建完成: {deploy_dir.absolute()}") - return True - -def create_deployment_package(): - """创建部署包""" - dist_dir = Path('dist') - deploy_dir = Path('deploy') - - if deploy_dir.exists(): - shutil.rmtree(deploy_dir) - - deploy_dir.mkdir() - - # 尝试复制可执行文件 - exe_file = dist_dir / 'cloud-drive-server' - if exe_file.exists(): - shutil.copy2(exe_file, deploy_dir) - print(f"[OK] 复制可执行文件到 {deploy_dir}") - return True - else: - print("警告: 未找到可执行文件,创建简单部署包") - return create_simple_package() - -def main(): - """主函数""" - parser = argparse.ArgumentParser(description='云盘后端Linux打包工具(无共享库版)') - parser.add_argument('--clean', action='store_true', help='仅清理构建目录') - parser.add_argument('--no-clean', action='store_true', help='跳过清理步骤') - parser.add_argument('--simple', action='store_true', help='创建简单部署包(不使用PyInstaller)') - - args = parser.parse_args() - - print("=== 云盘后端Linux打包工具(无共享库版) ===") - print(f"当前目录: {os.getcwd()}") - - # 检查环境 - check_python_version() - check_dependencies() - - # 清理构建目录 - if args.clean: - clean_build_dirs() - print("[OK] 清理完成") - return - - if not args.no_clean: - clean_build_dirs() - - if args.simple: - # 直接创建简单部署包 - create_simple_package() - else: - # 尝试PyInstaller打包 - if run_pyinstaller_noshared(): - create_deployment_package() - else: - print("PyInstaller打包失败,创建简单部署包...") - create_simple_package() - - print("\n=== 打包完成 ===") - print("部署包位置: ./deploy/") - - # 检查部署包内容 - deploy_dir = Path('deploy') - if (deploy_dir / 'cloud-drive-server').exists(): - print("✓ 可执行文件: cloud-drive-server") - print("运行方式: ./cloud-drive-server") - else: - print("✓ Python源代码包") - print("运行方式: ./start.sh") - print("安装方式: ./install_simple.sh") - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/backend/build_with_docker.sh b/backend/build_with_docker.sh deleted file mode 100644 index 325e4ec..0000000 --- a/backend/build_with_docker.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# 使用Docker构建Linux可执行文件 - -echo "=== 使用Docker构建Linux可执行文件 ===" - -# 构建Docker镜像 -echo "构建Docker镜像..." -docker build -f Dockerfile.build -t cloud-drive-builder . - -# 运行构建容器并提取结果 -echo "运行构建..." -docker run --rm -v $(pwd):/output cloud-drive-builder bash -c "cp -r /opt/cloud-drive/* /output/" - -echo "=== 构建完成 ===" -echo "Linux可执行文件已生成到当前目录" -echo "文件列表:" -ls -la cloud-drive-server start.sh README.md .env.example - -echo "" -echo "部署文件已准备就绪,可以上传到Linux服务器" -echo "建议下一步:" -echo "1. 将所有文件上传到Linux服务器" -echo "2. 运行 sudo ./install.sh 进行安装" \ No newline at end of file diff --git a/backend/check_files_table.py b/backend/check_files_table.py deleted file mode 100644 index 9f25155..0000000 --- a/backend/check_files_table.py +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/env python3 -""" -检查数据库files表和实际文件存储情况 -""" - -import mysql.connector -import os -import hashlib - -def check_database_files(): - """检查数据库中的文件记录""" - - try: - # 连接数据库 - conn = mysql.connector.connect( - host="101.126.85.76", - user="mytest_db", - password="mytest_db", - database="mytest_db" - ) - cursor = conn.cursor() - - # 查询files表中的所有记录 - cursor.execute(""" - SELECT id, user_id, original_filename, filename, file_path, file_size, - file_hash, mime_type, created_at - FROM files - ORDER BY created_at DESC - """) - - files = cursor.fetchall() - - print("=== 数据库 files 表中的记录 ===") - if files: - for file in files: - (id, user_id, original_filename, filename, file_path, - file_size, file_hash, mime_type, created_at) = file - - print(f"ID: {id}") - print(f" 用户ID: {user_id}") - print(f" 原始文件名: {original_filename}") - print(f" 存储文件名: {filename}") - print(f" 文件路径: {file_path}") - print(f" 文件大小: {file_size} bytes") - print(f" 文件哈希: {file_hash}") - print(f" MIME类型: {mime_type}") - print(f" 创建时间: {created_at}") - print("-" * 50) - else: - print("files 表中没有记录") - - print(f"\n总记录数: {len(files)}") - - # 检查每个文件是否真实存在 - print("\n=== 文件存在性检查 ===") - existing_count = 0 - missing_files = [] - - for file in files: - (id, user_id, original_filename, filename, file_path, - file_size, file_hash, mime_type, created_at) = file - - full_path = os.path.join("uploads", filename) - if os.path.exists(full_path): - existing_count += 1 - print(f"✅ ID {id}: {original_filename} - 文件存在") - - # 检查文件大小 - actual_size = os.path.getsize(full_path) - if actual_size != file_size: - print(f" ⚠️ 文件大小不匹配! 数据库: {file_size}, 实际: {actual_size}") - - # 检查文件哈希 - try: - with open(full_path, 'rb') as f: - content = f.read() - actual_hash = hashlib.sha256(content).hexdigest() - if actual_hash != file_hash: - print(f" ❌ 文件哈希不匹配! 数据库: {file_hash}") - print(f" 实际: {actual_hash}") - except Exception as e: - print(f" ❌ 无法读取文件或计算哈希: {e}") - - else: - missing_files.append((id, original_filename, filename)) - print(f"❌ ID {id}: {original_filename} - 文件不存在!") - - print(f"\n实际存在的文件: {existing_count}") - print(f"缺失的文件: {len(missing_files)}") - - if missing_files: - print("\n缺失文件详情:") - for (id, original_filename, filename) in missing_files: - print(f" ID {id}: {original_filename} (应存储为: {filename})") - - except Exception as e: - print(f"数据库查询出错: {e}") - finally: - if 'conn' in locals() and conn.is_connected(): - cursor.close() - conn.close() - -def check_uploads_directory(): - """检查uploads目录中的实际文件""" - - print("\n=== uploads 目录中的实际文件 ===") - - uploads_dir = "uploads" - if os.path.exists(uploads_dir): - files = os.listdir(uploads_dir) - if files: - print(f"目录: {uploads_dir}") - print(f"文件数量: {len(files)}") - - for file in files: - file_path = os.path.join(uploads_dir, file) - file_size = os.path.getsize(file_path) - - # 计算文件哈希 - try: - with open(file_path, 'rb') as f: - content = f.read() - file_hash = hashlib.sha256(content).hexdigest() - - # 尝试读取文本内容 - try: - with open(file_path, 'r', encoding='utf-8') as f: - text_content = f.read() - content_preview = text_content[:100] + "..." if len(text_content) > 100 else text_content - content_preview = repr(content_preview) # 显示引号和特殊字符 - except: - content_preview = "(二进制文件)" - - except Exception as e: - file_hash = f"无法计算哈希: {e}" - content_preview = f"无法读取: {e}" - - print(f"\n📄 {file}") - print(f" 大小: {file_size} bytes") - print(f" 哈希: {file_hash}") - print(f" 内容预览: {content_preview}") - else: - print(f"目录 {uploads_dir} 为空") - else: - print(f"目录 {uploads_dir} 不存在") - -def check_file_integrity(): - """检查文件完整性,对比数据库和实际文件""" - - print("\n=== 文件完整性检查 ===") - - try: - # 连接数据库 - conn = mysql.connector.connect( - host="101.126.85.76", - user="mytest_db", - password="mytest_db", - database="mytest_db" - ) - cursor = conn.cursor() - - # 查询所有文件 - cursor.execute("SELECT id, filename, file_hash, file_size FROM files") - db_files = cursor.fetchall() - - integrity_issues = [] - - for (id, filename, expected_hash, expected_size) in db_files: - full_path = os.path.join("uploads", filename) - - if os.path.exists(full_path): - # 检查大小 - actual_size = os.path.getsize(full_path) - if actual_size != expected_size: - integrity_issues.append(f"ID {id}: 文件大小不匹配 (期望: {expected_size}, 实际: {actual_size})") - continue - - # 检查哈希 - try: - with open(full_path, 'rb') as f: - content = f.read() - actual_hash = hashlib.sha256(content).hexdigest() - - if actual_hash != expected_hash: - integrity_issues.append(f"ID {id}: 文件哈希不匹配") - print(f" 期望哈希: {expected_hash}") - print(f" 实际哈希: {actual_hash}") - - except Exception as e: - integrity_issues.append(f"ID {id}: 无法计算文件哈希 - {e}") - else: - integrity_issues.append(f"ID {id}: 文件不存在") - - if integrity_issues: - print(f"❌ 发现 {len(integrity_issues)} 个完整性问题:") - for issue in integrity_issues: - print(f" - {issue}") - else: - print("✅ 所有文件完整性检查通过!") - - except Exception as e: - print(f"完整性检查出错: {e}") - finally: - if 'conn' in locals() and conn.is_connected(): - cursor.close() - conn.close() - -if __name__ == "__main__": - check_database_files() - check_uploads_directory() - check_file_integrity() - - print("\n=== 总结 ===") - print("文件存储情况:") - print("1. 数据库存储文件的元数据信息") - print("2. 实际文件存储在 backend/uploads/ 目录") - print("3. 文件名使用UUID格式确保唯一性") - print("4. 通过file_hash确保文件完整性") - print("5. 支持文件去重功能") \ No newline at end of file diff --git a/backend/check_tables.py b/backend/check_tables.py deleted file mode 100644 index 1c96abd..0000000 --- a/backend/check_tables.py +++ /dev/null @@ -1,51 +0,0 @@ -import pymysql -from app.core.config import settings - -def check_user_login_table(): - try: - # 解析连接字符串 - import re - pattern = r'mysql\+pymysql://([^:]+):([^@]+)@([^:]+):(\d+)/(.+)' - match = re.match(pattern, settings.DATABASE_URL) - - if match: - username, password, host, port, database = match.groups() - - connection = pymysql.connect( - host=host, - port=int(port), - user=username, - password=password, - database=database, - charset='utf8mb4' - ) - - with connection.cursor() as cursor: - # 检查user_login表结构 - print("=== user_login表结构 ===") - cursor.execute("DESCRIBE user_login") - columns = cursor.fetchall() - for column in columns: - print(f"{column[0]}: {column[1]} {column[2]} {column[3]} {column[4]}") - - print("\n=== user_login表数据示例 ===") - cursor.execute("SELECT * FROM user_login LIMIT 3") - rows = cursor.fetchall() - for row in rows: - print(row) - - print("\n=== 检查是否有用户相关的表 ===") - cursor.execute("SHOW TABLES LIKE '%user%'") - user_tables = cursor.fetchall() - for table in user_tables: - print(f"- {table[0]}") - - connection.close() - return True - - except Exception as e: - print(f"检查表结构失败: {str(e)}") - return False - -if __name__ == "__main__": - check_user_login_table() \ No newline at end of file diff --git a/backend/clean_server.py b/backend/clean_server.py deleted file mode 100644 index ac9c84c..0000000 --- a/backend/clean_server.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python3 -print("Starting Cloud Drive Application Server...") - -import sys -print(f"Python version: {sys.version}") - -try: - from fastapi import FastAPI - from fastapi.middleware.cors import CORSMiddleware - import uvicorn - print("FastAPI dependencies available") - - app = FastAPI( - title="Cloud Drive API", - description="Modern Cloud Storage Web Application Backend API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - @app.get("/") - async def root(): - return { - "message": "Cloud Drive API", - "version": "1.0.1", - "docs": "/docs", - "health": "/api/v1/health" - } - - @app.get("/health") - async def health(): - return {"status": "healthy"} - - @app.get("/api/v1/health") - async def api_health(): - import time - return { - "status": "healthy", - "timestamp": time.time(), - "version": "1.0.0" - } - - @app.get("/test") - async def test(): - return {"test": "ok", "server": "working"} - - try: - from app.core.config import settings - print("Full app module available") - mode = "full" - except ImportError: - print("Using simplified mode") - mode = "simplified" - - @app.get("/info") - async def info(): - return { - "mode": mode, - "python_version": str(sys.version), - "status": "running" - } - - print("=" * 50) - print("Server URLs:") - print(" http://localhost:8080") - print(" http://localhost:8080/docs") - print(" http://localhost:8080/api/v1/health") - print("=" * 50) - print("Press Ctrl+C to stop server") - print() - - uvicorn.run( - app, - host="0.0.0.0", - port=8080, - reload=False, - access_log=True, - log_level="info" - ) - -except ImportError as e: - print(f"Dependency import failed: {e}") - print("Please run: pip install fastapi uvicorn") - sys.exit(1) -except Exception as e: - print(f"Startup failed: {e}") - sys.exit(1) \ No newline at end of file diff --git a/backend/cleanup_test_user.py b/backend/cleanup_test_user.py deleted file mode 100644 index e17ff41..0000000 --- a/backend/cleanup_test_user.py +++ /dev/null @@ -1,20 +0,0 @@ -from app.core.database import SessionLocal -from app.models.user import User - -def cleanup_test_user(): - """清理测试用户""" - db = SessionLocal() - try: - # 删除测试用户 - test_user = db.query(User).filter(User.username == "peng").first() - if test_user: - db.delete(test_user) - db.commit() - print("已删除测试用户 'peng'") - else: - print("未找到测试用户 'peng'") - finally: - db.close() - -if __name__ == "__main__": - cleanup_test_user() \ No newline at end of file diff --git a/backend/create_tables.py b/backend/create_tables.py deleted file mode 100644 index 98e1b99..0000000 --- a/backend/create_tables.py +++ /dev/null @@ -1,33 +0,0 @@ -from sqlalchemy import create_engine, text -from app.core.config import settings -from app.core.database import Base -from app.models import User - -def create_user_table(): - try: - print(f"连接数据库: {settings.DATABASE_URL}") - - # 创建数据库引擎 - engine = create_engine(settings.DATABASE_URL, echo=True) - - # 创建所有表 - Base.metadata.create_all(bind=engine) - print("users表创建成功!") - - # 检查表是否创建成功 - with engine.connect() as conn: - result = conn.execute(text("DESCRIBE users")) - columns = result.fetchall() - print("\nusers表结构:") - for column in columns: - print(f" {column[0]}: {column[1]} {column[2]} {column[3]} {column[4]}") - - print("\n数据库表创建完成!") - return True - - except Exception as e: - print(f"创建表失败: {str(e)}") - return False - -if __name__ == "__main__": - create_user_table() \ No newline at end of file diff --git a/backend/create_test_user.py b/backend/create_test_user.py deleted file mode 100644 index 9bd4005..0000000 --- a/backend/create_test_user.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python3 -""" -创建测试用户的脚本 -""" - -import requests -import hashlib -import mysql.connector - -# API基础URL -BASE_URL = "http://localhost:8000/api/v1" - -def create_user_directly(): - """直接在数据库中创建用户""" - try: - # 连接数据库 - conn = mysql.connector.connect( - host="101.126.85.76", - user="mytest_db", - password="mytest_db", - database="mytest_db" - ) - cursor = conn.cursor() - - # 检查用户是否已存在 - cursor.execute("SELECT id FROM users WHERE username = %s", ("testuser",)) - user = cursor.fetchone() - - if user: - print(f"用户已存在,ID: {user[0]}") - return user[0] - - # 创建密码哈希 - password = "TestPass123!" - password_hash = hashlib.sha256(password.encode()).hexdigest() - - # 插入用户 - insert_query = """ - INSERT INTO users (username, email, password_hash, storage_quota, storage_used, is_active, is_verified) - VALUES (%s, %s, %s, %s, %s, %s, %s) - """ - cursor.execute(insert_query, ( - "testuser", - "test@example.com", - password_hash, - 104857600, # 100MB - 0, - True, - True - )) - - user_id = cursor.lastrowid - conn.commit() - - print(f"用户创建成功,ID: {user_id}") - return user_id - - except Exception as e: - print(f"创建用户出错: {e}") - return None - finally: - if 'conn' in locals() and conn.is_connected(): - cursor.close() - conn.close() - -if __name__ == "__main__": - user_id = create_user_directly() - if user_id: - print(f"测试用户ID: {user_id}") - else: - print("创建用户失败") \ No newline at end of file diff --git a/backend/debug_download.py b/backend/debug_download.py deleted file mode 100644 index b5d1f4e..0000000 --- a/backend/debug_download.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/env python3 -""" -调试文件下载接口的脚本 -""" - -import requests -import mysql.connector -import os -import json - -# API基础URL -BASE_URL = "http://localhost:8000/api/v1" - -def debug_download_issue(): - """调试下载接口问题""" - - print("=== 调试文件下载接口 ===") - - # 检查数据库中的文件信息 - try: - conn = mysql.connector.connect( - host="101.126.85.76", - user="mytest_db", - password="mytest_db", - database="mytest_db" - ) - cursor = conn.cursor() - - # 查询所有文件 - cursor.execute(""" - SELECT id, user_id, original_filename, filename, file_path, file_size, - file_hash, mime_type, created_at - FROM files - ORDER BY id - """) - files = cursor.fetchall() - - print("数据库中的文件记录:") - for file in files: - (id, user_id, original_filename, filename, file_path, - file_size, file_hash, mime_type, created_at) = file - print(f"ID: {id}, 用户ID: {user_id}, 文件名: {original_filename}") - print(f" 存储路径: {file_path}") - print(f" 文件大小: {file_size} bytes") - print(f" 创建时间: {created_at}") - print("-" * 50) - - cursor.close() - conn.close() - - except Exception as e: - print(f"数据库查询出错: {e}") - return - - # 测试特定文件下载 - test_cases = [ - {"user_id": 3, "file_id": 2, "description": "用户3下载文件2(axurerp-48.png)"}, - {"user_id": 3, "file_id": 3, "description": "用户3下载文件3(axurerp-128.png)"}, - {"user_id": 8, "file_id": 4, "description": "用户8下载文件4(hash_demo.txt)"}, - {"user_id": 3, "file_id": 4, "description": "用户3下载文件4(权限测试)"}, - {"user_id": 1, "file_id": 2, "description": "用户1下载文件2(不存在用户)"}, - {"user_id": 3, "file_id": 999, "description": "用户3下载文件999(不存在文件)"}, - ] - - for test_case in test_cases: - user_id = test_case["user_id"] - file_id = test_case["file_id"] - description = test_case["description"] - - print(f"\n=== 测试: {description} ===") - print(f"入参: user_id={user_id}, file_id={file_id}") - - try: - data = { - "user_id": user_id, - "file_id": file_id - } - - response = requests.post( - f"{BASE_URL}/files/download", - json=data - ) - - print(f"HTTP状态码: {response.status_code}") - - if response.status_code == 200: - # 下载成功 - content_length = len(response.content) - print(f"下载成功! 文件大小: {content_length} bytes") - - # 保存下载的文件用于检查 - save_filename = f"downloaded_user{user_id}_file{file_id}" - if content_length > 0: - with open(save_filename, 'wb') as f: - f.write(response.content) - print(f"文件已保存为: {save_filename}") - else: - print("警告: 下载的文件为空") - - # 显示内容预览 - try: - if response.headers.get('content-type', '').startswith('text/'): - text_content = response.content.decode('utf-8') - preview = text_content[:100] + "..." if len(text_content) > 100 else text_content - print(f"内容预览: {preview}") - else: - print("二进制文件,无法预览内容") - except: - print("无法预览文件内容") - - else: - # 下载失败 - print(f"下载失败!") - print(f"响应内容: {response.text}") - - # 尝试解析JSON错误信息 - try: - error_data = response.json() - print(f"错误详情: {json.dumps(error_data, indent=2, ensure_ascii=False)}") - except: - print("无法解析错误响应") - - except Exception as e: - print(f"请求出错: {e}") - -def check_file_access_permission(): - """检查文件访问权限""" - - print("\n=== 检查文件访问权限 ===") - - # 检查uploads目录权限 - uploads_dir = "uploads" - if os.path.exists(uploads_dir): - print(f"uploads目录存在: {os.path.abspath(uploads_dir)}") - - # 检查目录权限 - try: - test_file = os.path.join(uploads_dir, "test_permission.txt") - with open(test_file, 'w') as f: - f.write("test") - - if os.path.exists(test_file): - os.remove(test_file) - print("uploads目录读写权限正常") - else: - print("uploads目录权限异常") - except Exception as e: - print(f"无法在uploads目录写入文件: {e}") - else: - print("uploads目录不存在") - - # 检查数据库文件记录与实际文件的对应关系 - try: - conn = mysql.connector.connect( - host="101.126.85.76", - user="mytest_db", - password="mytest_db", - database="mytest_db" - ) - cursor = conn.cursor() - - cursor.execute("SELECT id, user_id, filename, file_path FROM files ORDER BY id") - files = cursor.fetchall() - - print("\n文件记录与实际文件对应关系:") - for (id, user_id, filename, file_path) in files: - full_path = os.path.join("uploads", filename) - exists = os.path.exists(full_path) - if exists: - size = os.path.getsize(full_path) - print(f"ID {id}: 文件存在 ({size} bytes)") - else: - print(f"ID {id}: 文件不存在 - {full_path}") - - cursor.close() - conn.close() - - except Exception as e: - print(f"检查文件对应关系出错: {e}") - -def test_download_with_curl(): - """使用curl测试下载接口""" - - print("\n=== 使用curl测试下载接口 ===") - - test_cases = [ - {"user_id": 3, "file_id": 2}, - {"user_id": 3, "file_id": 3}, - ] - - for test_case in test_cases: - user_id = test_case["user_id"] - file_id = test_case["file_id"] - - print(f"\n测试 curl - 用户ID: {user_id}, 文件ID: {file_id}") - - curl_command = f'''curl -X POST "{BASE_URL}/files/download" \\ --H "Content-Type: application/json" \\ --d '{{"user_id": {user_id}, "file_id": {file_id}}}' \\ --v''' - - print("命令:") - print(curl_command) - print("(请在终端中手动执行此命令)") - -if __name__ == "__main__": - debug_download_issue() - check_file_access_permission() - test_download_with_curl() - - print("\n=== 调试总结 ===") - print("如果下载失败,可能的原因:") - print("1. 文件不存在或已被删除") - print("2. 用户ID与文件不匹配") - print("3. uploads目录权限问题") - print("4. 实际文件大小为0字节") - print("5. 下载接口实现逻辑问题") \ No newline at end of file diff --git a/backend/debug_download_detailed.py b/backend/debug_download_detailed.py deleted file mode 100644 index 37009f6..0000000 --- a/backend/debug_download_detailed.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python3 -""" -详细调试下载接口的每个步骤 -""" - -import requests -import os -import mysql.connector - -def debug_download_step_by_step(): - """逐步调试下载过程""" - - print("=== 详细下载接口调试 ===") - - # 测试参数 - user_id = 3 - file_id = 22 - - print(f"测试参数: user_id={user_id}, file_id={file_id}") - - # 步骤1: 检查数据库中的文件记录 - print("\n--- 步骤1: 检查数据库记录 ---") - try: - conn = mysql.connector.connect( - host='101.126.85.76', - user='mytest_db', - password='mytest_db', - database='mytest_db' - ) - cursor = conn.cursor() - - cursor.execute(''' - SELECT id, user_id, original_filename, filename, file_path, file_size, mime_type - FROM files - WHERE id = %s AND user_id = %s - ''', (file_id, user_id)) - - file_record = cursor.fetchone() - - if file_record: - id, db_user_id, original_filename, filename, file_path, file_size, mime_type = file_record - print(f"✅ 数据库记录找到:") - print(f" 文件ID: {id}") - print(f" 用户ID: {db_user_id}") - print(f" 原始文件名: {original_filename}") - print(f" 存储文件名: {filename}") - print(f" 文件路径: {file_path}") - print(f" 文件大小: {file_size} bytes") - print(f" MIME类型: {mime_type}") - else: - print("❌ 数据库中没有找到匹配的记录") - return - - cursor.close() - conn.close() - - except Exception as e: - print(f"❌ 数据库查询失败: {e}") - return - - # 步骤2: 检查实际文件是否存在 - print("\n--- 步骤2: 检查实际文件 ---") - - if os.path.exists(file_path): - actual_size = os.path.getsize(file_path) - print(f"✅ 文件存在:") - print(f" 路径: {os.path.abspath(file_path)}") - print(f" 实际大小: {actual_size} bytes") - - if actual_size == file_size: - print("✅ 文件大小匹配数据库记录") - else: - print(f"⚠️ 文件大小不匹配: 数据库{file_size} vs 实际{actual_size}") - - # 检查文件可读性 - if os.access(file_path, os.R_OK): - print("✅ 文件可读") - - # 读取文件内容验证 - try: - with open(file_path, 'r', encoding='utf-8') as f: - content = f.read() - print(f"✅ 文件内容可读,长度: {len(content)} 字符") - print(f" 内容预览: {content[:50]}...") - except Exception as e: - print(f"❌ 读取文件内容失败: {e}") - else: - print("❌ 文件不可读 - 权限问题") - else: - print(f"❌ 文件不存在: {file_path}") - return - - # 步骤3: 测试API下载请求 - print("\n--- 步骤3: 测试API下载请求 ---") - - try: - download_data = {'user_id': user_id, 'file_id': file_id} - - print(f"发送请求: POST /api/v1/files/download") - print(f"请求体: {download_data}") - - response = requests.post( - 'http://localhost:8000/api/v1/files/download', - json=download_data, - timeout=10 - ) - - print(f"响应状态码: {response.status_code}") - print(f"响应头: {dict(response.headers)}") - - if response.status_code == 200: - print("✅ 下载成功!") - - content_type = response.headers.get('content-type', '') - content_length = len(response.content) - - print(f" 响应类型: {content_type}") - print(f" 内容长度: {content_length} bytes") - - if content_type.startswith('text/'): - text_content = response.text - print(f" 文本内容长度: {len(text_content)} 字符") - print(f" 文本内容预览: {text_content[:50]}...") - - # 验证内容 - if len(text_content) == file_size / 2: # 大约UTF-8字符数 - print("✅ 内容大小预期范围内") - else: - print(f"⚠️ 内容大小异常: 预期~{file_size//2}字符,实际{len(text_content)}字符") - else: - print(" 二进制内容,无法显示预览") - - else: - print("❌ 下载失败!") - print(f"错误响应: {response.text}") - - # 尝试解析JSON错误 - try: - error_data = response.json() - print(f"错误详情: {error_data}") - except: - print("无法解析错误响应") - - except Exception as e: - print(f"❌ API请求失败: {e}") - import traceback - traceback.print_exc() - -if __name__ == "__main__": - debug_download_step_by_step() \ No newline at end of file diff --git a/backend/debug_email_duplicate.py b/backend/debug_email_duplicate.py deleted file mode 100644 index 3a13c78..0000000 --- a/backend/debug_email_duplicate.py +++ /dev/null @@ -1,48 +0,0 @@ -import sys -import traceback -from app.core.database import SessionLocal -from app.services.user_service import UserService -from app.schemas.auth import UserRegister - -def debug_email_duplicate(): - """调试邮箱重复问题""" - try: - print("=== 调试邮箱重复问题 ===") - - db = SessionLocal() - user_service = UserService(db) - - # 先检查现有用户 - print("1. 检查现有用户...") - existing_user = user_service.get_user_by_email("user@example.com") - if existing_user: - print(f" 找到现有用户: ID={existing_user.id}, 用户名={existing_user.username}, 邮箱={existing_user.email}") - else: - print(" 未找到现有用户") - - # 尝试创建重复邮箱的用户 - print("\n2. 尝试创建重复邮箱的用户...") - user_data = UserRegister( - username="test_duplicate", - email="user@example.com", # 重复邮箱 - password="TestPass123!", - confirm_password="TestPass123!" - ) - - try: - user = user_service.create_user(user_data) - print(f" 用户创建成功: {user.id}") - except Exception as e: - print(f" 用户创建失败: {e}") - print(f" 异常类型: {type(e).__name__}") - print(f" 异常详情: {e.detail if hasattr(e, 'detail') else '无详情'}") - traceback.print_exc() - - db.close() - - except Exception as e: - print(f"调试过程出错: {e}") - traceback.print_exc() - -if __name__ == "__main__": - debug_email_duplicate() \ No newline at end of file diff --git a/backend/debug_register.py b/backend/debug_register.py deleted file mode 100644 index 3cae6e5..0000000 --- a/backend/debug_register.py +++ /dev/null @@ -1,78 +0,0 @@ -import sys -import traceback -from app.core.database import SessionLocal -from app.core.security import get_password_hash -from app.models.user import User - -def debug_password_hashing(): - """测试密码哈希功能""" - try: - print("测试密码哈希功能...") - password = "Stringst1@" - hashed = get_password_hash(password) - print(f"密码哈希成功: {hashed[:50]}...") - return True - except Exception as e: - print(f"密码哈希失败: {str(e)}") - traceback.print_exc() - return False - -def debug_user_creation(): - """测试用户创建""" - try: - print("\n测试用户创建...") - - db = SessionLocal() - - # 检查用户是否已存在 - existing_user = db.query(User).filter(User.username == "peng").first() - if existing_user: - print("用户 'peng' 已存在,删除旧记录...") - db.delete(existing_user) - db.commit() - - # 创建新用户 - password_hash = get_password_hash("Stringst1@") - print(f"密码哈希生成成功") - - new_user = User( - username="peng", - email="user@example.com", - password_hash=password_hash, - is_active=True, - is_verified=False - ) - - db.add(new_user) - db.commit() - db.refresh(new_user) - - print(f"用户创建成功! ID: {new_user.id}") - - # 验证用户 - user = db.query(User).filter(User.username == "peng").first() - if user: - print(f"用户验证成功: {user.username}, {user.email}") - - db.close() - return True - - except Exception as e: - print(f"用户创建失败: {str(e)}") - traceback.print_exc() - return False - -if __name__ == "__main__": - print("=== 调试用户注册问题 ===") - - # 测试密码哈希 - if not debug_password_hashing(): - print("密码哈希有问题,退出") - sys.exit(1) - - # 测试用户创建 - if not debug_user_creation(): - print("用户创建有问题,退出") - sys.exit(1) - - print("\n=== 调试完成,一切正常 ===") \ No newline at end of file diff --git a/backend/debug_start.py b/backend/debug_start.py deleted file mode 100644 index 0a57de5..0000000 --- a/backend/debug_start.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python3 -# 带诊断信息的启动脚本 - -import socket -import sys -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware -import uvicorn - -# 检查端口是否可用 -def check_port(port): - try: - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.bind(('0.0.0.0', port)) - return True - except OSError: - return False - -# 获取本机IP -def get_local_ip(): - try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("8.8.8.8", 80)) - ip = s.getsockname()[0] - s.close() - return ip - except: - return "127.0.0.1" - -app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" -) - -# 更宽松的CORS配置 -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -@app.get("/") -async def root(): - return { - "message": "云盘应用 API", - "version": "1.0.0", - "docs": "/docs", - "health": "/health" - } - -@app.get("/health") -async def health(): - return { - "status": "healthy", - "message": "服务运行正常" - } - -@app.get("/debug") -async def debug_info(): - return { - "python_version": sys.version, - "working_directory": ".", - "available_endpoints": [ - "/", - "/health", - "/debug", - "/docs", - "/redoc", - "/openapi.json" - ] - } - -if __name__ == "__main__": - port = 8000 - - print("🔍 启动前诊断...") - print(f"Python版本: {sys.version}") - print(f"工作目录: {(await debug_info())['working_directory']}") - - # 检查端口 - if not check_port(port): - print(f"❌ 端口 {port} 被占用,尝试使用端口 8001") - port = 8001 - - local_ip = get_local_ip() - - print(f"🚀 启动云盘后端服务...") - print("=" * 60) - print(f"📍 本地访问: http://localhost:{port}") - print(f"📍 网络访问: http://{local_ip}:{port}") - print(f"📚 API文档: http://localhost:{port}/docs") - print(f"📚 网络文档: http://{local_ip}:{port}/docs") - print(f"❤️ 健康检查: http://localhost:{port}/health") - print(f"🔧 调试信息: http://localhost:{port}/debug") - print(f"⏹️ 按 Ctrl+C 停止服务") - print("=" * 60) - - # 启动时打印所有路由 - @app.on_event("startup") - async def startup_event(): - print("\n📋 可用路由:") - for route in app.routes: - if hasattr(route, 'path') and hasattr(route, 'methods'): - print(f" {list(route.methods)} {route.path}") - print() - - try: - uvicorn.run( - app, - host="0.0.0.0", # 允许外部访问 - port=port, - reload=False, - access_log=True, # 显示访问日志 - log_level="info" - ) - except Exception as e: - print(f"❌ 启动失败: {e}") - print("\n💡 尝试的解决方案:") - print("1. 检查防火墙设置") - print("2. 尝试其他端口: python debug_start.py") - print("3. 检查是否有其他程序占用端口") \ No newline at end of file diff --git a/backend/debug_upload_steps.py b/backend/debug_upload_steps.py deleted file mode 100644 index b08ac9f..0000000 --- a/backend/debug_upload_steps.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python3 -""" -逐步调试文件上传过程的每个步骤 -""" - -import requests -import io -import os - -def debug_upload_step_by_step(): - """逐步调试上传过程""" - - print("=== 步骤1: 准备测试文件 ===") - test_content = b"Debug upload content - step by step analysis" - print(f"原始内容大小: {len(test_content)} bytes") - print(f"原始内容: {test_content}") - print() - - print("=== 步骤2: 创建模拟上传文件 ===") - file_obj = io.BytesIO(test_content) - file_obj.seek(0) - print(f"BytesIO对象创建成功") - print(f"当前位置: {file_obj.tell()}") - print() - - print("=== 步骤3: 准备请求数据 ===") - files = { - 'file': ('debug_step_test.txt', file_obj, 'text/plain') - } - data = { - 'user_id': 3, - 'description': 'Step by step debug test', - 'tags': 'debug,step', - 'is_public': 'false' - } - print("请求数据准备完成") - print() - - print("=== 步骤4: 发送上传请求 ===") - try: - response = requests.post('http://localhost:8000/api/v1/files/upload', files=files, data=data) - print(f"响应状态码: {response.status_code}") - print(f"响应头: {dict(response.headers)}") - - if response.status_code == 201: - result = response.json() - print("=== 步骤5: 上传成功分析 ===") - if result.get('success'): - file_info = result['data']['file'] - file_id = file_info['id'] - filename = file_info['filename'] - db_size = file_info['file_size'] - - print(f"数据库记录:") - print(f" 文件ID: {file_id}") - print(f" 存储文件名: {filename}") - print(f" 数据库大小: {db_size} bytes") - print(f" 预期大小: {len(test_content)} bytes") - - # 检查磁盘文件 - print("\n=== 步骤6: 磁盘文件分析 ===") - file_path = os.path.join('uploads', filename) - print(f"预期路径: {file_path}") - - if os.path.exists(file_path): - actual_size = os.path.getsize(file_path) - print(f"实际文件大小: {actual_size} bytes") - - if actual_size == 0: - print("❌ 文件损坏: 大小为0") - elif actual_size == len(test_content): - print("✅ 文件完整") - - # 验证内容 - with open(file_path, 'rb') as f: - actual_content = f.read() - - if actual_content == test_content: - print("✅ 内容完全匹配") - else: - print("❌ 内容不匹配") - print(f"预期: {test_content}") - print(f"实际: {actual_content}") - else: - print(f"⚠️ 大小不匹配: {actual_size} != {len(test_content)}") - - # 读取部分内容检查 - try: - with open(file_path, 'rb') as f: - actual_content = f.read(min(100, actual_size)) - print(f"实际内容预览: {actual_content}") - except Exception as e: - print(f"无法读取文件内容: {e}") - else: - print("❌ 文件不存在于磁盘") - - # 检查目录 - upload_dir = 'uploads' - if os.path.exists(upload_dir): - print(f"uploads目录存在") - files_in_dir = os.listdir(upload_dir) - print(f"目录中的文件: {files_in_dir}") - else: - print("uploads目录不存在") - - else: - print("上传返回失败:", result) - else: - print("=== 步骤5: 上传失败分析 ===") - print(f"HTTP状态码: {response.status_code}") - print(f"响应内容: {response.text}") - - # 尝试解析错误 - try: - error_data = response.json() - print(f"错误详情: {error_data}") - except: - print("无法解析错误响应") - - except Exception as e: - print(f"请求异常: {e}") - import traceback - traceback.print_exc() - -if __name__ == "__main__": - debug_upload_step_by_step() \ No newline at end of file diff --git a/backend/demo_file_hash.py b/backend/demo_file_hash.py deleted file mode 100644 index 8286e5b..0000000 --- a/backend/demo_file_hash.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env python3 -""" -演示文件哈希原理和还原功能的脚本 -""" - -import hashlib -import requests -import os - -# API基础URL -BASE_URL = "http://localhost:8000/api/v1" -USER_ID = 8 - -def calculate_sha256_hash(file_content: bytes) -> str: - """计算文件的SHA-256哈希值""" - return hashlib.sha256(file_content).hexdigest() - -def upload_test_file_with_hash(): - """上传测试文件并展示哈希计算过程""" - - # 创建测试文件内容 - original_content = "Hello World! 这是演示文件哈希的测试内容。\n包含中文和English混合内容。" - - print(f"📄 原始文件内容:") - print(f"'{original_content}'") - print(f"📏 文件大小: {len(original_content.encode('utf-8'))} bytes") - print() - - # 计算哈希值 - file_hash = calculate_sha256_hash(original_content.encode('utf-8')) - print(f"🔒 计算SHA-256哈希值:") - print(f"{file_hash}") - print() - - # 上传文件 - try: - files = { - "file": ("demo_hash_test.txt", original_content.encode('utf-8'), "text/plain") - } - data = { - "user_id": USER_ID, - "description": "演示文件哈希功能", - "tags": "demo,hash,test", - "is_public": "false" - } - - response = requests.post( - f"{BASE_URL}/files/upload", - files=files, - data=data - ) - - if response.status_code == 201: - result = response.json() - if result.get("success"): - file_info = result["data"]["file"] - server_hash = file_info["file_hash"] - file_id = file_info["id"] - - print(f"✅ 文件上传成功!") - print(f"📋 文件ID: {file_id}") - print(f"📁 服务器存储的文件名: {file_info['filename']}") - print(f"🔒 服务器计算的哈希值: {server_hash}") - print() - - # 验证哈希值一致性 - if file_hash == server_hash: - print(f"✅ 哈希值验证通过! 客户端和服务器计算结果一致") - else: - print(f"❌ 哈希值验证失败! 客户端和服务器计算结果不一致") - print(f" 客户端: {file_hash}") - print(f" 服务器: {server_hash}") - - return file_id, original_content, file_hash - else: - print(f"❌ 上传失败: {response.text}") - return None, None, None - - except Exception as e: - print(f"❌ 上传出错: {e}") - return None, None, None - -def download_and_verify_file(file_id: int, original_content: str, original_hash: str): - """下载文件并验证完整性""" - - print(f"\n📥 开始下载和验证文件...") - - try: - # 下载文件 - data = { - "user_id": USER_ID, - "file_id": file_id - } - - response = requests.post( - f"{BASE_URL}/files/download", - json=data - ) - - if response.status_code == 200: - downloaded_content = response.content.decode('utf-8') - - print(f"📄 下载的文件内容:") - print(f"'{downloaded_content}'") - print() - - # 验证内容完整性 - if downloaded_content == original_content: - print(f"✅ 文件内容完整性验证通过!") - else: - print(f"❌ 文件内容完整性验证失败!") - print(f" 原始内容: '{original_content}'") - print(f" 下载内容: '{downloaded_content}'") - - # 计算下载文件的哈希值 - downloaded_hash = calculate_sha256_hash(downloaded_content.encode('utf-8')) - print(f"🔒 下载文件的哈希值:") - print(f"{downloaded_hash}") - print() - - # 验证哈希值 - if downloaded_hash == original_hash: - print(f"✅ 下载文件哈希验证通过! 文件完整性得到保证") - else: - print(f"❌ 下载文件哈希验证失败! 文件可能已损坏") - print(f" 原始哈希: {original_hash}") - print(f" 下载哈希: {downloaded_hash}") - - else: - print(f"❌ 下载失败: {response.text}") - - except Exception as e: - print(f"❌ 下载过程出错: {e}") - -def demonstrate_file_duplication(): - """演示文件去重功能""" - - print(f"\n🔄 演示文件去重功能...") - print(f"尝试上传相同内容的文件,系统应该拒绝重复上传...") - - # 创建与之前相同内容的文件 - duplicate_content = "Hello World! 这是演示文件哈希的测试内容。\n包含中文和English混合内容。" - - try: - files = { - "file": ("duplicate_file.txt", duplicate_content.encode('utf-8'), "text/plain") - } - data = { - "user_id": USER_ID, - "description": "重复文件测试", - "tags": "duplicate,test", - "is_public": "false" - } - - response = requests.post( - f"{BASE_URL}/files/upload", - files=files, - data=data - ) - - if response.status_code == 409: # 409 Conflict 表示文件已存在 - result = response.json() - print(f"✅ 文件去重功能正常工作!") - print(f"📋 系统检测到文件已存在,拒绝重复上传") - print(f"📄 原始文件名: {result.get('detail', {}).get('filename', 'Unknown')}") - elif response.status_code == 201: - print(f"⚠️ 文件去重功能可能未正常工作,重复上传成功了") - else: - print(f"❌ 测试失败: {response.text}") - - except Exception as e: - print(f"❌ 测试过程出错: {e}") - -def show_file_location_on_server(): - """显示文件在服务器上的存储位置""" - - print(f"\n📁 文件在服务器上的存储位置:") - print(f"后端上传目录: backend/uploads/") - - # 列出uploads目录中的文件 - try: - if os.path.exists("backend/uploads"): - files = os.listdir("backend/uploads") - if files: - print(f"当前存储的文件:") - for file in files: - file_path = os.path.join("backend/uploads", file) - file_size = os.path.getsize(file_path) - print(f" 📄 {file} ({file_size} bytes)") - - # 计算并显示文件的哈希值 - with open(file_path, 'rb') as f: - content = f.read() - file_hash = calculate_sha256_hash(content) - print(f" 🔒 SHA-256: {file_hash}") - else: - print(f" (目录为空)") - else: - print(f" (uploads目录不存在)") - except Exception as e: - print(f" 无法读取目录: {e}") - -if __name__ == "__main__": - print("🔐 文件哈希原理演示") - print("=" * 50) - - # 1. 上传测试文件 - file_id, original_content, original_hash = upload_test_file_with_hash() - - if file_id: - # 2. 下载并验证文件 - download_and_verify_file(file_id, original_content, original_hash) - - # 3. 演示文件去重 - demonstrate_file_duplication() - - # 4. 显示文件存储位置 - show_file_location_on_server() - - print(f"\n🎉 演示完成!") - print(f"📚 关键知识点:") - print(f" • SHA-256哈希值用于验证文件完整性") - print(f" • 相同内容的文件具有相同的哈希值") - print(f" • 系统通过哈希值检测重复文件") - print(f" • 文件在上传、存储、下载过程中保持完整性") - else: - print(f"\n❌ 演示失败,无法上传测试文件") \ No newline at end of file diff --git a/backend/docs_fix.py b/backend/docs_fix.py deleted file mode 100644 index de31582..0000000 --- a/backend/docs_fix.py +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/env python3 -# 专门解决docs无法访问问题的脚本 - -import subprocess -import socket -import sys -from pathlib import Path - -def check_fastapi_docs(): - """检查FastAPI docs相关的常见问题""" - print("🔍 FastAPI Docs 诊断工具") - print("=" * 50) - - # 1. 检查FastAPI版本 - try: - import fastapi - print(f"✓ FastAPI版本: {fastapi.__version__}") - except ImportError: - print("❌ FastAPI未安装") - return False - - # 2. 检查uvicorn版本 - try: - import uvicorn - print(f"✓ Uvicorn版本: {uvicorn.__version__}") - except ImportError: - print("❌ Uvicorn未安装") - return False - - # 3. 检查端口占用 - print("\n📡 网络诊断:") - for port in [8000, 8001, 8002]: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(1) - result = sock.connect_ex(('127.0.0.1', port)) - if result == 0: - print(f"❌ 端口 {port} 被占用") - else: - print(f"✓ 端口 {port} 可用") - sock.close() - - # 4. 获取本机IP - try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("8.8.8.8", 80)) - local_ip = s.getsockname()[0] - s.close() - print(f"✓ 本机IP: {local_ip}") - except: - local_ip = "127.0.0.1" - print(f"⚠️ 使用回环地址: {local_ip}") - - # 5. 测试不同的host配置 - print("\n🧪 测试不同配置:") - - test_configs = [ - ("127.0.0.1", "仅本地访问"), - ("0.0.0.0", "允许外部访问"), - ("localhost", "主机名访问") - ] - - for host, desc in test_configs: - print(f" {host} - {desc}") - - return True, local_ip - -def create_working_server(): - """创建可以正常访问docs的服务器""" - print("\n🔧 创建可用的服务器配置...") - - server_content = '''#!/usr/bin/env python3 -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware -import uvicorn -import socket - -app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc", - openapi_url="/openapi.json" -) - -# 确保CORS配置正确 -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -@app.get("/") -async def root(): - return { - "message": "云盘应用 API", - "version": "1.0.0", - "docs": "/docs", - "redoc": "/redoc", - "openapi": "/openapi.json" - } - -@app.get("/health") -async def health(): - return { - "status": "healthy", - "docs_available": True - } - -@app.get("/test-docs") -async def test_docs(): - """测试docs是否可用""" - return { - "docs_url": "/docs", - "redoc_url": "/redoc", - "openapi_url": "/openapi.json", - "message": "如果看到这个页面,说明服务正常运行,请尝试访问 /docs" - } - -def get_available_port(): - """获取可用端口""" - for port in range(8000, 8010): - try: - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.bind(('0.0.0.0', port)) - return port - except OSError: - continue - return None - -if __name__ == "__main__": - port = get_available_port() - if port is None: - print("❌ 无法找到可用端口") - sys.exit(1) - - # 获取本机IP - try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("8.8.8.8", 80)) - local_ip = s.getsockname()[0] - s.close() - except: - local_ip = "127.0.0.1" - - print(f"🚀 启动服务在端口 {port}") - print("=" * 60) - print(f"📍 本地访问:") - print(f" 根路径: http://localhost:{port}") - print(f" API文档: http://localhost:{port}/docs") - print(f" ReDoc: http://localhost:{port}/redoc") - print(f" 测试页面: http://localhost:{port}/test-docs") - print("") - print(f"📍 网络访问:") - print(f" 根路径: http://{local_ip}:{port}") - print(f" API文档: http://{local_ip}:{port}/docs") - print(f" ReDoc: http://{local_ip}:{port}/redoc") - print("=" * 60) - print("💡 如果无法访问,请检查:") - print(" 1. 防火墙设置") - print(" 2. 网络连接") - print(" 3. 浏览器是否阻止访问") - print(" 4. 尝试不同的浏览器") - print("⏹️ 按 Ctrl+C 停止服务") - print("=" * 60) - - try: - uvicorn.run( - app, - host="0.0.0.0", - port=port, - reload=False, - access_log=True, - log_level="info" - ) - except KeyboardInterrupt: - print("\\n服务已停止") - except Exception as e: - print(f"❌ 启动失败: {e}") -''' - - with open('working_server.py', 'w', encoding='utf-8') as f: - f.write(server_content) - - print("✓ 已创建 working_server.py") - return True - -def test_curl_commands(): - """提供curl测试命令""" - print("\n🌐 提供测试命令:") - - print("\\n1. 测试根路径:") - print("curl http://localhost:8000") - - print("\\n2. 测试健康检查:") - print("curl http://localhost:8000/health") - - print("\\n3. 测试API文档端点:") - print("curl http://localhost:8000/docs") - - print("\\n4. 测试OpenAPI JSON:") - print("curl http://localhost:8000/openapi.json") - - print("\\n5. 测试ReDoc:") - print("curl http://localhost:8000/redoc") - -def main(): - """主函数""" - # 检查环境 - success, local_ip = check_fastapi_docs() - - if not success: - print("\\n❌ 环境检查失败,请安装必要的依赖") - print("pip install fastapi uvicorn") - return - - # 创建可用服务器 - create_working_server() - - # 提供测试命令 - test_curl_commands() - - print("\\n" + "=" * 60) - print("🎯 解决方案:") - print("1. 运行: python working_server.py") - print("2. 在浏览器中访问显示的URL") - print("3. 如果仍然无法访问,请检查:") - print(" - 防火墙设置") - print(" - 浏览器阻止") - print(" - 网络代理设置") - print("=" * 60) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/backend/fix_cors.sh b/backend/fix_cors.sh deleted file mode 100644 index 2edfc9b..0000000 --- a/backend/fix_cors.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/bash - -# CORS跨域问题快速修复脚本 - -echo "=== CORS跨域问题修复工具 ===" - -# 检查当前目录 -if [ ! -f "main.py" ]; then - echo "错误: 请在包含main.py的项目根目录下运行此脚本" - exit 1 -fi - -echo "当前目录: $(pwd)" - -# 1. 更新配置文件 -echo "" -echo "1. 更新CORS配置..." - -# 更新config.py -echo "更新 app/core/config.py..." -sed -i 's/ALLOWED_HOSTS: List\[str\] = \[.*\]/ALLOWED_HOSTS: List[str] = ["*"] # 允许所有域名访问/' app/core/config.py - -if [ $? -eq 0 ]; then - echo "✓ config.py 更新成功" -else - echo "✗ config.py 更新失败,请手动检查" -fi - -# 2. 更新.env文件 -echo "" -echo "2. 更新环境配置..." -if [ -f ".env" ]; then - # 备份原始文件 - cp .env .env.backup.$(date +%Y%m%d_%H%M%S) - - # 更新CORS配置 - sed -i 's/ALLOWED_HOSTS=\[.*\]/ALLOWED_HOSTS=["*"]/' .env - - if grep -q 'ALLOWED_HOSTS=\["\*"\]' .env; then - echo "✓ .env 文件更新成功" - else - echo "✗ .env 文件更新失败,请手动检查" - fi -else - echo ".env 文件不存在,创建新的配置..." - cat > .env << EOF -# 基础配置 -ENVIRONMENT=production -DEBUG=false - -# 数据库配置 -DATABASE_URL=mysql+pymysql://用户名:密码@localhost:3306/数据库名 - -# Redis配置 -REDIS_URL=redis://localhost:6379 - -# JWT配置 -JWT_SECRET_KEY=your-super-secret-jwt-key-change-in-production-$(date +%s) -JWT_ALGORITHM=HS256 -JWT_EXPIRE_MINUTES=30 - -# 文件上传配置 -UPLOAD_DIR=uploads -MAX_FILE_SIZE=10485760 - -# CORS配置 -ALLOWED_HOSTS=["*"] -EOF - echo "✓ .env 文件创建成功" -fi - -# 3. 验证配置 -echo "" -echo "3. 验证CORS配置..." - -# 检查config.py -if grep -q 'ALLOWED_HOSTS: List\[str\] = \["\*"\]' app/core/config.py; then - echo "✓ config.py CORS配置正确" -else - echo "✗ config.py CORS配置可能有问题" -fi - -# 检查.env文件 -if grep -q 'ALLOWED_HOSTS=\["\*"\]' .env; then - echo "✓ .env CORS配置正确" -else - echo "✗ .env CORS配置可能有问题" -fi - -# 4. 重启服务提示 -echo "" -echo "4. 重启服务..." -echo "配置更新完成,请重启应用以使配置生效" -echo "" -echo "重启方式:" -echo "1. 如果应用正在运行,请按 Ctrl+C 停止" -echo "2. 然后重新启动: python main.py" -echo "3. 或者使用启动脚本: ./start_app.sh" -echo "" -echo "如果使用Docker部署:" -echo "1. 重新构建镜像: docker build -t cloud-drive-backend:latest ." -echo "2. 重新运行容器: docker run -d -p 8002:8002 cloud-drive-backend:latest" - -# 5. 测试CORS -echo "" -echo "5. CORS测试建议..." -echo "重启后,可以通过以下方式测试CORS:" -echo "1. 浏览器开发者工具 -> Network -> 查看请求头" -echo "2. 检查是否有 'Access-Control-Allow-Origin: *' 头" -echo "3. 使用curl测试: curl -H 'Origin: http://example.com' -H 'Access-Control-Request-Method: POST' -H 'Access-Control-Request-Headers: X-Requested-With' -X OPTIONS http://localhost:8002/api/v1/health" - -echo "" -echo "=== CORS修复完成 ===" -echo "" -echo "注意事项:" -echo "- 允许所有域名访问 (\"*\") 仅适用于开发和测试环境" -echo "- 生产环境建议设置具体的允许域名列表" -echo "- 如需更安全的CORS配置,请手动修改 ALLOWED_HOSTS" \ No newline at end of file diff --git a/backend/fix_database_connection.sh b/backend/fix_database_connection.sh deleted file mode 100644 index 761d7b1..0000000 --- a/backend/fix_database_connection.sh +++ /dev/null @@ -1,194 +0,0 @@ -#!/bin/bash - -# 数据库连接问题修复脚本 - -echo "=== 数据库连接问题修复工具 ===" - -# 检查当前目录 -if [ ! -f "main.py" ]; then - echo "错误: 请在包含main.py的项目根目录下运行此脚本" - exit 1 -fi - -echo "当前目录: $(pwd)" - -# 1. 检查.env文件 -echo "" -echo "1. 检查环境配置..." - -if [ -f ".env" ]; then - echo "✓ .env 文件存在" - echo "当前数据库配置:" - grep "DATABASE_URL" .env || echo "DATABASE_URL 未设置" -else - echo "⚠ .env 文件不存在,正在创建..." - cat > .env << EOF -# 基础配置 -ENVIRONMENT=production -DEBUG=false - -# 数据库配置 - 请根据实际情况修改 -DATABASE_URL=mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db - -# Redis配置 -REDIS_URL=redis://localhost:6379 - -# JWT配置 -JWT_SECRET_KEY=your-super-secret-jwt-key-change-in-production-$(date +%s) -JWT_ALGORITHM=HS256 -JWT_EXPIRE_MINUTES=30 - -# 文件上传配置 -UPLOAD_DIR=uploads -MAX_FILE_SIZE=10485760 - -# CORS配置 -ALLOWED_HOSTS=["*"] -EOF - echo "✓ .env 文件创建成功" -fi - -# 2. 测试数据库连接 -echo "" -echo "2. 测试数据库连接..." - -# 创建测试脚本 -cat > test_db_connection.py << 'EOF' -#!/usr/bin/env python3 -import sys -import os -sys.path.insert(0, '.') - -try: - from app.core.config import settings - print(f"✓ 配置加载成功") - print(f"数据库URL: {settings.DATABASE_URL}") - - # 测试数据库连接 - from sqlalchemy import create_engine, text - engine = create_engine(settings.DATABASE_URL) - - with engine.connect() as conn: - result = conn.execute(text("SELECT VERSION()")) - version = result.fetchone()[0] - print(f"✓ 数据库连接成功: MySQL {version}") - - # 检查数据库是否存在 - result = conn.execute(text("SHOW DATABASES LIKE 'mytest_db'")) - if result.fetchone(): - print("✓ 数据库 'mytest_db' 存在") - else: - print("⚠ 数据库 'mytest_db' 不存在,需要创建") - -except ImportError as e: - print(f"✗ 导入错误: {e}") - print("请确保已安装所需依赖: pip install sqlalchemy pymysql") - sys.exit(1) -except Exception as e: - print(f"✗ 数据库连接失败: {e}") - print("") - print "可能的原因:" - print "1. 数据库服务器未启动" - print "2. 网络连接问题" - print "3. 用户名或密码错误" - print "4. 数据库不存在" - print "5. 防火墙阻止连接" - sys.exit(1) -EOF - -python3 test_db_connection.py - -if [ $? -eq 0 ]; then - echo "" - echo "✓ 数据库连接测试通过" -else - echo "" - echo "✗ 数据库连接测试失败" - echo "" - echo "解决方案:" - echo "1. 检查数据库服务是否运行" - echo "2. 验证数据库连接参数" - echo "3. 确认网络连通性" - echo "" - echo "请手动编辑 .env 文件中的 DATABASE_URL" - echo "格式: mysql+pymysql://用户名:密码@主机:端口/数据库名" - exit 1 -fi - -# 3. 检查Docker环境 -echo "" -echo "3. 检查Docker配置..." - -if [ -f "docker-compose.yml" ]; then - echo "✓ 发现 docker-compose.yml 文件" - echo "检查Docker数据库配置..." - - if grep -q "mysql:" docker-compose.yml; then - echo "⚠ 检测到Docker MySQL配置" - echo "如果使用Docker Compose,请确保:" - echo "1. 数据库服务已启动: docker-compose up -d mysql" - echo "2. 数据库主机名应为 'mysql' (服务名)" - echo "3. 确认网络配置正确" - - echo "" - echo "Docker数据库连接配置示例:" - echo "DATABASE_URL=mysql+pymysql://root:password@mysql:3306/mytest_db" - fi -fi - -# 4. 提供修复建议 -echo "" -echo "4. 修复建议..." - -echo "根据错误信息,应用尝试连接到 'mysql' 主机,但配置中是IP地址。" -echo "请检查以下配置:" -echo "" - -echo "选项1: 使用外部数据库 (推荐)" -echo "DATABASE_URL=mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db" -echo "" - -echo "选项2: 使用Docker数据库" -echo "DATABASE_URL=mysql+pymysql://root:password@mysql:3306/mytest_db" -echo "" - -echo "选项3: 使用本地数据库" -echo "DATABASE_URL=mysql+pymysql://root:password@localhost:3306/mytest_db" -echo "" - -# 5. 自动修复.env文件 -echo "5. 自动修复配置..." -if [ -f ".env" ]; then - # 备份原文件 - cp .env .env.backup.$(date +%Y%m%d_%H%M%S) - - # 确保使用正确的数据库URL - if grep -q "DATABASE_URL.*mysql.*mysql:" .env; then - echo "检测到Docker主机名配置,更新为外部数据库..." - sed -i 's|DATABASE_URL=mysql+pymysql://.*@mysql:.*|DATABASE_URL=mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db|' .env - elif ! grep -q "DATABASE_URL.*101.126.85.76" .env; then - echo "更新数据库连接配置..." - sed -i 's|DATABASE_URL=.*|DATABASE_URL=mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db|' .env - fi - - echo "✓ 数据库配置已更新" -fi - -# 6. 重启应用提示 -echo "" -echo "6. 重启应用..." -echo "配置更新完成,请重启应用以使配置生效" -echo "" -echo "重启方式:" -echo "1. 停止当前应用 (Ctrl+C)" -echo "2. 重新启动: python main.py" -echo "3. 或者使用启动脚本: ./start_app.sh" - -echo "" -echo "=== 数据库连接修复完成 ===" -echo "" -echo "如果问题仍然存在,请:" -echo "1. 确认数据库服务器地址正确: 101.126.85.76:3306" -echo "2. 确认用户名密码正确: mytest_db / mytest_db" -echo "3. 确认数据库名称正确: mytest_db" -echo "4. 测试网络连通性: telnet 101.126.85.76 3306" \ No newline at end of file diff --git a/backend/fix_dependencies.sh b/backend/fix_dependencies.sh deleted file mode 100644 index fcf20ef..0000000 --- a/backend/fix_dependencies.sh +++ /dev/null @@ -1,151 +0,0 @@ -#!/bin/bash - -# 依赖修复脚本 - 解决email-validator缺失问题 - -echo "=== 云盘后端依赖修复工具 ===" - -# 检查当前用户 -echo "当前用户: $(whoami)" -echo "用户ID: $EUID" - -# 1. 检查Python环境 -echo "" -echo "1. 检查Python环境..." -if ! command -v python3 &> /dev/null; then - echo "错误: 未找到python3" - exit 1 -fi -echo "✓ Python版本: $(python3 --version)" - -# 2. 检查pip -echo "" -echo "2. 检查pip..." -if ! command -v pip3 &> /dev/null; then - echo "错误: 未找到pip3" - exit 1 -fi -echo "✓ pip版本: $(pip3 --version)" - -# 3. 升级pip -echo "" -echo "3. 升级pip..." -if [ "$EUID" -eq 0 ]; then - pip3 install --upgrade pip -else - pip3 install --user --upgrade pip -fi -echo "✓ pip升级完成" - -# 4. 安装email-validator(单独安装确保成功) -echo "" -echo "4. 安装email-validator..." -if [ "$EUID" -eq 0 ]; then - pip3 install email-validator -else - pip3 install --user email-validator -fi - -if [ $? -eq 0 ]; then - echo "✓ email-validator安装成功" -else - echo "✗ email-validator安装失败" - exit 1 -fi - -# 5. 验证email-validator安装 -echo "" -echo "5. 验证email-validator安装..." -python3 -c "import email_validator; print('✓ email-validator导入成功')" || { - echo "✗ email-validator验证失败" - exit 1 -} - -# 6. 安装其他核心依赖 -echo "" -echo "6. 安装其他核心依赖..." -CORE_PACKAGES="fastapi uvicorn sqlalchemy pymysql redis python-jose passlib python-multipart pydantic pydantic-settings httpx python-dotenv alembic bcrypt" - -if [ "$EUID" -eq 0 ]; then - pip3 install $CORE_PACKAGES -else - pip3 install --user $CORE_PACKAGES -fi - -if [ $? -eq 0 ]; then - echo "✓ 核心依赖安装成功" -else - echo "✗ 核心依赖安装失败" - exit 1 -fi - -# 7. 验证核心包导入 -echo "" -echo "7. 验证核心包导入..." -python3 -c " -try: - import fastapi, uvicorn, sqlalchemy, pymysql, redis, jose, passlib, pydantic, httpx, alembic - print('✓ 所有核心包导入成功') -except ImportError as e: - print(f'✗ 包导入失败: {e}') - exit(1) -" || exit 1 - -# 8. 测试Pydantic配置 -echo "" -echo "8. 测试Pydantic配置..." -python3 -c " -try: - from pydantic import BaseModel, EmailStr - print('✓ Pydantic EmailStr类型可用') -except Exception as e: - print(f'✗ Pydantic EmailStr测试失败: {e}') - print('尝试重新安装pydantic[email]...') - exit(1) -" || { - echo "重新安装pydantic[email]..." - if [ "$EUID" -eq 0 ]; then - pip3 install "pydantic[email]" - else - pip3 install --user "pydantic[email]" - fi -} - -# 9. 测试应用导入 -echo "" -echo "9. 测试应用核心模块导入..." -python3 -c " -import sys -sys.path.insert(0, '.') -try: - from app.core.config import settings - print('✓ 应用配置模块导入成功') -except Exception as e: - print(f'✗ 应用配置导入失败: {e}') - print('可能需要检查应用代码') - exit(1) -" || { - echo "应用导入测试失败,但依赖已安装" -} - -echo "" -echo "=== 依赖修复完成 ===" -echo "" -echo "已成功安装的包:" -echo "- email-validator (邮件验证)" -echo "- fastapi (Web框架)" -echo "- uvicorn (ASGI服务器)" -echo "- sqlalchemy (ORM)" -echo "- pymysql (MySQL驱动)" -echo "- redis (Redis客户端)" -echo "- python-jose (JWT处理)" -echo "- passlib (密码处理)" -echo "- pydantic (数据验证)" -echo "- httpx (HTTP客户端)" -echo "- alembic (数据库迁移)" -echo "- bcrypt (密码哈希)" -echo "" -echo "现在可以运行应用:" -echo "python3 main.py" -echo "" -echo "或使用部署脚本:" -echo "./quick_deploy_linux.sh" \ No newline at end of file diff --git a/backend/fix_module_import.py b/backend/fix_module_import.py deleted file mode 100644 index cf1be3e..0000000 --- a/backend/fix_module_import.py +++ /dev/null @@ -1,264 +0,0 @@ -#!/usr/bin/env python3 -# 修复模块导入问题的脚本 - -import os -import sys -from pathlib import Path - -def check_project_structure(): - """检查项目结构""" - print("=== 检查项目结构 ===") - - current_dir = Path.cwd() - print(f"当前目录: {current_dir}") - - # 检查app目录 - app_dir = current_dir / 'app' - if app_dir.exists(): - print("✓ app目录存在") - else: - print("✗ app目录不存在") - return False - - # 检查app/core目录 - core_dir = app_dir / 'core' - if core_dir.exists(): - print("✓ app/core目录存在") - else: - print("✗ app/core目录不存在") - return False - - # 检查关键文件 - key_files = [ - 'app/__init__.py', - 'app/core/__init__.py', - 'app/core/config.py', - 'main.py' - ] - - for file_path in key_files: - if (current_dir / file_path).exists(): - print(f"✓ {file_path} 存在") - else: - print(f"✗ {file_path} 不存在") - return False - - return True - -def create_missing_files(): - """创建缺失的文件""" - print("\n=== 创建缺失文件 ===") - - current_dir = Path.cwd() - - # 创建app/__init__.py - app_init = current_dir / 'app' / '__init__.py' - if not app_init.exists(): - with open(app_init, 'w') as f: - f.write('"""云盘应用包"""\n') - print("✓ 创建 app/__init__.py") - - # 创建app/core/__init__.py - core_init = current_dir / 'app' / 'core' / '__init__.py' - if not core_init.exists(): - with open(core_init, 'w') as f: - f.write('"""核心模块包"""\n') - print("✓ 创建 app/core/__init__.py") - - # 创建app/core/config.py(如果不存在) - config_file = current_dir / 'app' / 'core' / 'config.py' - if not config_file.exists(): - config_content = '''from pydantic_settings import BaseSettings -from typing import List -import os - -class Settings(BaseSettings): - # 基础配置 - ENVIRONMENT: str = "development" - DEBUG: bool = True - - # 数据库配置 - DATABASE_URL: str = "mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db" - - # Redis配置 - REDIS_URL: str = "redis://localhost:6379" - - # JWT配置 - JWT_SECRET_KEY: str = "your-super-secret-jwt-key-change-in-production" - JWT_ALGORITHM: str = "HS256" - JWT_EXPIRE_MINUTES: int = 30 - JWT_REFRESH_EXPIRE_DAYS: int = 7 - - # CORS配置 - ALLOWED_HOSTS: List[str] = [ - "http://localhost:3000", - "http://localhost:3001", - "http://localhost:3002", - "http://localhost:3003", - "http://localhost:3004", - "http://127.0.0.1:3000", - "http://127.0.0.1:3001", - "http://127.0.0.1:3002", - "http://127.0.0.1:3003", - "http://127.0.0.1:3004", - "http://172.16.16.89:3000", - "http://172.16.16.89:3001", - "http://172.16.16.89:3002", - "http://172.16.16.89:3003", - "http://172.16.16.89:3004", - "*" - ] - - # 文件上传配置 - MAX_FILE_SIZE: int = 10 * 1024 * 1024 # 10MB - UPLOAD_DIR: str = "uploads" - ALLOWED_EXTENSIONS: List[str] = [ - # 图片 - ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg", - # 文档 - ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", - ".txt", ".rtf", ".csv", - # 压缩文件 - ".zip", ".rar", ".7z", ".tar", ".gz", - # 音频 - ".mp3", ".wav", ".flac", ".aac", ".ogg", - # 视频 - ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", - # 代码文件 - ".py", ".js", ".html", ".css", ".json", ".xml", ".yaml", ".yml", - ".java", ".cpp", ".c", ".h", ".cs", ".php", ".rb", ".go", - ".sql", ".sh", ".bat", ".ps1", ".md", ".log" - ] - - # 安全配置 - BCRYPT_ROUNDS: int = 12 - - class Config: - env_file = ".env" - case_sensitive = True - -settings = Settings() -''' - with open(config_file, 'w') as f: - f.write(config_content) - print("✓ 创建 app/core/config.py") - -def create_fixed_main_py(): - """创建修复版main.py""" - current_dir = Path.cwd() - main_file = current_dir / 'main.py' - - fixed_content = '''#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -云盘后端应用主入口 -""" - -import os -import sys -from pathlib import Path - -# 确保项目根目录在Python路径中 -current_dir = Path(__file__).parent -if str(current_dir) not in sys.path: - sys.path.insert(0, str(current_dir)) - -try: - from fastapi import FastAPI - from fastapi.middleware.cors import CORSMiddleware - from app.core.config import settings - from app.api.v1.endpoints import health, auth, files - import uvicorn - from datetime import datetime - - # 简单的日志打印函数 - def log_info(message): - """打印INFO级别日志""" - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - print(f"[{timestamp}] INFO: {message}") - - def log_error(message): - """打印ERROR级别日志""" - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - print(f"[{timestamp}] ERROR: {message}") - - def log_debug(message): - """打印DEBUG级别日志""" - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - print(f"[{timestamp}] DEBUG: {message}") - - # 确保logs目录存在 - logs_dir = current_dir / "logs" - logs_dir.mkdir(exist_ok=True) - - log_info("=== Server Starting ===") - log_info(f"Python version: {sys.version}") - log_info(f"Working directory: {os.getcwd()}") - log_info("Simple print logger configured") - - app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # CORS中间件 - app.add_middleware( - CORSMiddleware, - allow_origins=settings.ALLOWED_HOSTS, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - # 包含路由 - app.include_router(health.router, prefix="/api/v1", tags=["health"]) - app.include_router(auth.router, prefix="/api/v1/auth", tags=["authentication"]) - app.include_router(files.router, prefix="/api/v1/files", tags=["files"]) - - @app.get("/") - async def root(): - return {"message": "云盘应用 API", "version": "1.0.1"} - - if __name__ == "__main__": - uvicorn.run( - "main:app", - host="0.0.0.0", - port=8000, - reload=True if settings.ENVIRONMENT == "development" else False - ) - -except ImportError as e: - print(f"导入错误: {e}") - print("请确保已安装所有依赖: pip install -r requirements.txt") - print("或尝试安装基础依赖: pip install fastapi uvicorn sqlalchemy pymysql redis python-jose passlib python-multipart pydantic pydantic-settings httpx python-dotenv") - sys.exit(1) -except Exception as e: - print(f"启动错误: {e}") - sys.exit(1) -''' - - with open(main_file, 'w') as f: - f.write(fixed_content) - print("✓ 创建修复版 main.py") - -def main(): - """主函数""" - print("=== 修复模块导入问题 ===") - - # 检查项目结构 - if not check_project_structure(): - print("\\n项目结构有问题,开始修复...") - create_missing_files() - create_fixed_main_py() - - print("\\n=== 修复完成 ===") - print("现在可以运行:") - print("1. 激活虚拟环境: source venv/bin/activate") - print("2. 安装依赖: pip install -r requirements.txt") - print("3. 启动服务: python main.py") - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/backend/fix_permissions.sh b/backend/fix_permissions.sh deleted file mode 100644 index 1be4639..0000000 --- a/backend/fix_permissions.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/bash - -# 权限问题修复脚本 - -echo "=== 云盘后端权限修复工具 ===" - -# 检查当前用户 -echo "当前用户: $(whoami)" -echo "用户ID: $EUID" -echo "主目录: $HOME" -echo "当前目录: $(pwd)" - -# 1. 检查和创建.config目录 -echo "" -echo "1. 检查用户配置目录..." -if [ ! -d "$HOME/.config" ]; then - echo "创建 .config 目录..." - mkdir -p "$HOME/.config" || { - echo "错误: 无法创建 .config 目录" - exit 1 - } - echo "✓ .config 目录创建成功" -else - echo "✓ .config 目录已存在" -fi - -# 2. 检查和创建systemd用户目录 -echo "" -echo "2. 检查systemd用户目录..." -SYSTEMD_USER_DIR="$HOME/.config/systemd/user" - -if [ ! -d "$SYSTEMD_USER_DIR" ]; then - echo "创建systemd用户目录..." - mkdir -p "$SYSTEMD_USER_DIR" || { - echo "错误: 无法创建systemd用户目录" - echo "尝试使用sudo创建..." - sudo -u $(whoami) mkdir -p "$SYSTEMD_USER_DIR" || { - echo "错误: 无法创建systemd用户目录,尝试使用临时目录" - SYSTEMD_USER_DIR="/tmp/$(whoami)-systemd" - mkdir -p "$SYSTEMD_USER_DIR" - echo "使用临时目录: $SYSTEMD_USER_DIR" - } - } - echo "✓ systemd用户目录创建成功: $SYSTEMD_USER_DIR" -else - echo "✓ systemd用户目录已存在: $SYSTEMD_USER_DIR" -fi - -# 3. 检查目录权限 -echo "" -echo "3. 检查目录权限..." -echo ".config 目录权限: $(ls -ld $HOME/.config | awk '{print $1,$3,$4}')" -echo "systemd用户目录权限: $(ls -ld $SYSTEMD_USER_DIR | awk '{print $1,$3,$4}')" - -# 4. 测试写入权限 -echo "" -echo "4. 测试写入权限..." -TEST_FILE="$SYSTEMD_USER_DIR/.test_write" -if touch "$TEST_FILE" 2>/dev/null; then - echo "✓ 写入权限正常" - rm -f "$TEST_FILE" -else - echo "✗ 写入权限不足,尝试修复..." - chmod 755 "$HOME/.config" 2>/dev/null - chmod 755 "$SYSTEMD_USER_DIR" 2>/dev/null - - if touch "$TEST_FILE" 2>/dev/null; then - echo "✓ 权限修复成功" - rm -f "$TEST_FILE" - else - echo "✗ 权限修复失败" - echo "可能的解决方案:" - echo "1. 检查磁盘空间: df -h" - echo "2. 检查用户配额: quota -u $(whoami)" - echo "3. 检查文件系统权限: mount | grep home" - echo "4. 联系系统管理员" - exit 1 - fi -fi - -# 5. 检查systemd用户服务是否启用 -echo "" -echo "5. 检查systemd用户服务..." -if systemctl --user list-units --type=service --state=running &>/dev/null; then - echo "✓ systemd用户服务可用" -else - echo "⚠ systemd用户服务可能不可用" - echo "尝试启用用户systemd服务..." - - # 对于某些系统,需要启用linger - if command -v loginctl &> /dev/null; then - if loginctl show-user $(whoami) | grep -q "Linger=no"; then - echo "启用用户linger服务..." - loginctl enable-linger $(whoami) || echo "无法启用linger,可能需要管理员权限" - fi - fi -fi - -# 6. 创建测试服务文件 -echo "" -echo "6. 创建测试服务文件..." -SERVICE_FILE="$SYSTEMD_USER_DIR/cloud-drive.service" - -cat > "$SERVICE_FILE" << EOF -[Unit] -Description=Cloud Drive Backend Service -Documentation=https://github.com/your-repo/cloud-drive -After=network.target - -[Service] -Type=simple -WorkingDirectory=$(pwd) -ExecStart=$(pwd)/venv/bin/python $(pwd)/main.py -Restart=always -RestartSec=10 -StandardOutput=journal -StandardError=journal -SyslogIdentifier=cloud-drive - -[Install] -WantedBy=default.target -EOF - -if [ -f "$SERVICE_FILE" ]; then - echo "✓ 服务文件创建成功: $SERVICE_FILE" - echo "文件权限: $(ls -l $SERVICE_FILE | awk '{print $1,$3,$4}')" -else - echo "✗ 服务文件创建失败" - exit 1 -fi - -# 7. 测试systemd命令 -echo "" -echo "7. 测试systemd命令..." -if systemctl --user daemon-reload 2>/dev/null; then - echo "✓ systemd用户服务重载成功" -else - echo "⚠ systemd用户服务重载失败" - echo "错误信息: $(systemctl --user daemon-reload 2>&1)" -fi - -echo "" -echo "=== 权限修复完成 ===" -echo "" -echo "服务管理命令:" -echo "重载服务: systemctl --user daemon-reload" -echo "启用服务: systemctl --user enable cloud-drive" -echo "启动服务: systemctl --user start cloud-drive" -echo "查看状态: systemctl --user status cloud-drive" -echo "查看日志: journalctl --user -u cloud-drive -f" -echo "" -echo "如果systemd命令不可用,请使用手动管理脚本:" -echo "启动: ./start.sh" -echo "停止: ./stop.sh" -echo "状态: ./status.sh" \ No newline at end of file diff --git a/backend/fix_python_shared_lib.sh b/backend/fix_python_shared_lib.sh deleted file mode 100644 index 74870cd..0000000 --- a/backend/fix_python_shared_lib.sh +++ /dev/null @@ -1,244 +0,0 @@ -#!/bin/bash -# Python共享库问题修复脚本 - -echo "=== Python共享库问题修复脚本 ===" - -# 检测Python环境 -echo "1. 检测Python环境..." -python3 --version -echo "Python路径: $(which python3)" - -# 检测是否支持共享库 -echo "" -echo "2. 检测共享库支持..." -if python3 -c "import sys; print('Shared library support:', hasattr(sys, 'getdlopenflags'))" 2>/dev/null; then - echo "✓ Python支持共享库" -else - echo "✗ Python不支持共享库" -fi - -# 尝试方案一:使用修复的配置文件 -echo "" -echo "3. 方案一:使用修复的配置文件打包..." - -# 下载修复的配置文件 -cat > build_noshared.spec << 'EOF' -# -*- mode: python ; coding: utf-8 -*- -# 适用于没有共享库的Python环境的PyInstaller配置 - -import sys -from pathlib import Path - -# 项目根目录 -ROOT_DIR = Path.cwd() - -# 需要包含的数据文件 -datas = [ - (str(ROOT_DIR / 'app'), 'app'), # 包含整个app目录 - ('.env.example', '.'), # 包含环境配置示例文件 -] - -# 可选数据文件(如果存在才包含) -optional_files = [ - ('database', 'database'), # 包含数据库相关文件 -] - -# 添加可选数据文件 -for src, dst in optional_files: - src_path = ROOT_DIR / src - if src_path.exists(): - datas.append((src, dst)) - print(f"包含可选数据文件: {src}") - else: - print(f"跳过可选数据文件: {src} (不存在)") - -# 隐式导入的模块 -hiddenimports = [ - 'fastapi', 'uvicorn', 'starlette', 'pydantic', 'sqlalchemy', - 'passlib', 'python_jose', 'pymysql', 'redis', 'httpx', 'loguru', - 'python_dotenv', 'alembic', 'email.utils', 'yaml', 'toml', - 'json', 'base64', 'hashlib', 'datetime', 'uuid', 'os', 'sys', - 'pathlib', 'typing', 'collections', 'itertools', 'functools', - 'time', 'math', 're', 'socket', 'threading', 'asyncio', - 'cryptography', 'jinja2', 'mimetypes', 'tempfile', 'shutil', - 'argparse', 'codecs', 'encodings', 'random', 'secrets', - 'urllib', 'http', 'signal', 'multiprocessing' -] - -block_cipher = None - -a = Analysis( - ['main.py'], - pathex=[str(ROOT_DIR)], - binaries=[], - datas=datas, - hiddenimports=hiddenimports, - hookspath=[], - hooksconfig={}, - runtime_hooks=[], - excludes=[ - 'Pillow', 'numpy', 'scipy', 'matplotlib', 'pandas', - 'torch', 'tensorflow', 'jupyter', 'notebook', 'ipython', - 'sphinx', 'pytest', 'setuptools', 'pip', 'wheel', - 'PyQt5', 'PyQt6', 'PySide2', 'PySide6', 'tkinter' - ], - win_no_prefer_redirects=False, - win_private_assemblies=False, - cipher=block_cipher, - noarchive=False, -) - -pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) - -exe = EXE( - pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, - [], - name='cloud-drive-server', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=False, - upx_exclude=[], - runtime_tmpdir=None, - console=True, - disable_windowed_traceback=False, - argv_emulation=False, - target_arch=None, - codesign_identity=None, - entitlements_file=None, -) -EOF - -echo "✓ 已创建 build_noshared.spec" - -# 尝试打包 -echo "尝试使用修复配置打包..." -if pyinstaller --clean --noupx build_noshared.spec; then - echo "✓ 方案一成功:可执行文件已生成" - echo "文件位置: dist/cloud-drive-server" - - # 创建部署包 - mkdir -p deploy - cp dist/cloud-drive-server deploy/ - cp .env.example deploy/ - - # 创建启动脚本 - cat > deploy/start.sh << 'STARTEOF' -#!/bin/bash -cd "$(dirname "$0")" -if [ ! -f ".env" ]; then - cp .env.example .env -fi -mkdir -p logs uploads -./cloud-drive-server -STARTEOF - chmod +x deploy/start.sh - - echo "✓ 部署包已创建: deploy/" - echo "现在可以运行: cd deploy && ./start.sh" - exit 0 -else - echo "✗ 方案一失败" -fi - -# 尝试方案二:单文件模式 -echo "" -echo "4. 方案二:尝试单文件模式..." -if pyinstaller --clean --noupx --onefile main.py; then - echo "✓ 方案二成功:单文件可执行文件已生成" - - mkdir -p deploy - cp dist/main deploy/cloud-drive-server - cp .env.example deploy/ - - cat > deploy/start.sh << 'STARTEOF' -#!/bin/bash -cd "$(dirname "$0")" -if [ ! -f ".env" ]; then - cp .env.example .env -fi -mkdir -p logs uploads -./cloud-drive-server -STARTEOF - chmod +x deploy/start.sh - - echo "✓ 部署包已创建: deploy/" - exit 0 -else - echo "✗ 方案二失败" -fi - -# 尝试方案三:Python源代码部署 -echo "" -echo "5. 方案三:创建Python源代码部署包..." - -mkdir -p deploy -cp -r app deploy/ -cp main.py deploy/ -cp requirements.txt deploy/ -cp .env.example deploy/ - -# 创建启动脚本 -cat > deploy/start.sh << 'STARTEOF' -#!/bin/bash -cd "$(dirname "$0")" - -# 检查Python环境 -if ! command -v python3 &> /dev/null; then - echo "错误: 未找到python3" - exit 1 -fi - -# 检查虚拟环境 -if [ ! -d "venv" ]; then - echo "创建虚拟环境..." - python3 -m venv venv - source venv/bin/activate - pip install -r requirements.txt -else - source venv/bin/activate -fi - -# 检查环境文件 -if [ ! -f ".env" ]; then - cp .env.example .env - echo "已创建 .env 文件,请根据需要修改配置" -fi - -# 创建必要目录 -mkdir -p logs uploads - -# 启动服务 -echo "启动云盘后端服务..." -python main.py -STARTEOF - -chmod +x deploy/start.sh - -# 创建安装脚本 -cat > deploy/install.sh << 'INSTALLEOF' -#!/bin/bash -INSTALL_DIR="$HOME/cloud-drive" -echo "安装云盘后端服务到 $INSTALL_DIR" -mkdir -p "$INSTALL_DIR" -cp -r * "$INSTALL_DIR/" -echo "安装完成!" -echo "进入目录: cd $INSTALED_DIR" -echo "启动服务: ./start.sh" -INSTALLEOF - -chmod +x deploy/install.sh - -echo "✓ 方案三成功:Python源代码部署包已创建" -echo "部署位置: deploy/" -echo "使用方法:" -echo " 1. cd deploy" -echo " 2. ./start.sh" - -echo "" -echo "=== 修复完成 ===" -echo "建议使用方案三(Python源代码部署),这最稳定可靠。" \ No newline at end of file diff --git a/backend/fix_venv.sh b/backend/fix_venv.sh deleted file mode 100644 index 1a16359..0000000 --- a/backend/fix_venv.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash - -# 虚拟环境修复脚本 - -echo "=== 虚拟环境修复工具 ===" - -# 检查当前目录 -if [ ! -f "main.py" ]; then - echo "错误: 请在包含main.py的项目根目录下运行此脚本" - exit 1 -fi - -echo "当前目录: $(pwd)" -echo "当前Python版本: $(python3 --version)" - -# 备份现有虚拟环境(如果存在) -if [ -d "venv" ]; then - echo "发现现有虚拟环境,正在备份..." - mv venv venv_backup_$(date +%Y%m%d_%H%M%S) - echo "✓ 现有虚拟环境已备份" -fi - -# 创建新的虚拟环境 -echo "正在创建新的虚拟环境..." -python3 -m venv venv - -if [ $? -eq 0 ]; then - echo "✓ 虚拟环境创建成功" -else - echo "✗ 虚拟环境创建失败" - echo "可能的原因:" - echo "1. python3-venv 未安装" - echo "2. 权限不足" - echo "3. 磁盘空间不足" - echo "" - echo "尝试安装 python3-venv:" - echo "sudo apt-get install python3-venv # Ubuntu/Debian" - echo "sudo yum install python3-virtualenv # CentOS/RHEL" - exit 1 -fi - -# 验证虚拟环境文件 -echo "验证虚拟环境文件..." -if [ -f "venv/bin/activate" ]; then - echo "✓ 激活脚本存在: venv/bin/activate" - - # 显示虚拟环境信息 - echo "虚拟环境内容:" - ls -la venv/bin/ | head -5 - - # 测试激活 - echo "测试虚拟环境激活..." - source venv/bin/activate - echo "✓ 虚拟环境激活成功" - echo "Python路径: $(which python)" - echo "Python版本: $(python --version)" - - # 升级pip - echo "升级pip..." - pip install --upgrade pip - echo "✓ pip升级完成" - -else - echo "✗ 激活脚本不存在" - echo "显示venv目录内容:" - ls -la venv/ 2>/dev/null || echo "venv目录为空或不存在" - exit 1 -fi - -echo "" -echo "=== 修复完成 ===" -echo "虚拟环境已成功创建并可以正常使用" -echo "" -echo "下一步操作:" -echo "1. 重新运行部署脚本: ./deploy_linux.sh" -echo "2. 或者手动激活并安装依赖:" -echo " source venv/bin/activate" -echo " pip install -r requirements.txt" \ No newline at end of file diff --git a/backend/fixed_file_upload.py b/backend/fixed_file_upload.py deleted file mode 100644 index f306327..0000000 --- a/backend/fixed_file_upload.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python3 -""" -修复版文件上传测试 - 绕过有问题的业务逻辑 -""" - -import requests -import os -import uuid -import hashlib -import time - -def fixed_upload_file(): - """修复版文件上传""" - - print("=== 修复版5KB文件上传测试 ===") - - # 1. 生成5KB测试内容 - content = "Fixed upload test content. " * 200 # 约5KB - content = content[:5000] # 确保正好5000字符 - - print(f"1. 生成测试内容: {len(content)} 字符") - - # 2. 先通过API上传获取文件ID和记录 - test_file_path = 'temp_test_upload.txt' - with open(test_file_path, 'w', encoding='utf-8') as f: - f.write(content) - - print("2. 创建临时测试文件") - - # 3. 通过API上传(这会创建数据库记录但文件为0字节) - with open(test_file_path, 'rb') as f: - files = { - 'file': ('fixed_test_5kb.txt', f, 'text/plain') - } - data = { - 'user_id': 3, - 'description': 'Fixed upload test', - 'tags': 'test,fixed', - 'is_public': 'false' - } - - response = requests.post('http://localhost:8000/api/v1/files/upload', files=files, data=data) - - if response.status_code == 201: - result = response.json() - if result.get('success'): - file_info = result['data']['file'] - file_id = file_info['id'] - filename = file_info['filename'] - - print(f"3. API上传成功 - 文件ID: {file_id}, 文件名: {filename}") - - # 4. 手动修复文件内容 - file_path = os.path.join('uploads', filename) - print(f"4. 手动修复文件: {file_path}") - - # 直接写入正确内容 - with open(file_path, 'w', encoding='utf-8') as f: - f.write(content) - - # 5. 验证修复结果 - if os.path.exists(file_path): - actual_size = os.path.getsize(file_path) - print(f"5. 修复后文件大小: {actual_size} bytes") - - if actual_size == len(content.encode('utf-8')): - print("SUCCESS: 文件修复成功!") - - # 验证内容 - with open(file_path, 'r', encoding='utf-8') as f: - read_content = f.read() - - if read_content == content: - print("SUCCESS: 内容验证通过!") - - # 6. 测试下载 - print("6. 测试下载功能...") - download_data = {'user_id': 3, 'file_id': file_id} - download_response = requests.post('http://localhost:8000/api/v1/files/download', json=download_data) - - if download_response.status_code == 200: - downloaded_content = download_response.content.decode('utf-8') - if downloaded_content == content: - print("SUCCESS: 下载功能正常!") - print(f"下载内容长度: {len(downloaded_content)} 字符") - return True, file_id, filename - else: - print("ERROR: 下载内容不匹配!") - else: - print(f"ERROR: 下载失败 - {download_response.status_code}") - else: - print("ERROR: 内容验证失败!") - else: - print(f"ERROR: 修复后大小不匹配: {actual_size}") - else: - print("ERROR: 修复后文件不存在!") - else: - print("API上传失败:", result) - else: - print("API上传失败:", response.text) - - # 清理临时文件 - if os.path.exists(test_file_path): - os.remove(test_file_path) - - return False, None, None - -if __name__ == "__main__": - success, file_id, filename = fixed_upload_file() - - if success: - print(f"\n=== 修复成功 ===") - print(f"可以使用的文件ID: {file_id}") - print(f"文件名: {filename}") - print(f"现在可以通过正常方式下载这个完整的5KB文件!") - else: - print(f"\n=== 修复失败 ===") - print("需要进一步调试文件保存逻辑") \ No newline at end of file diff --git a/backend/install.sh b/backend/install.sh deleted file mode 100644 index fbfee8b..0000000 --- a/backend/install.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/bash -# 云盘后端服务安装脚本 - -set -e - -# 配置变量 -SERVICE_NAME="cloud-drive" -SERVICE_USER="cloud-drive" -INSTALL_DIR="/opt/cloud-drive" -SERVICE_FILE="cloud-drive.service" - -echo "=== 云盘后端服务安装脚本 ===" - -# 检查是否为root用户 -if [ "$EUID" -ne 0 ]; then - echo "错误: 请使用root权限运行此脚本" - exit 1 -fi - -# 检查系统 -if [ -f /etc/os-release ]; then - . /etc/os-release - echo "检测到系统: $NAME $VERSION" -else - echo "警告: 无法检测系统版本" -fi - -# 创建服务用户 -echo "创建服务用户..." -if ! id "$SERVICE_USER" &>/dev/null; then - useradd -r -s /bin/false -d "$INSTALL_DIR" "$SERVICE_USER" - echo "✓ 创建用户 $SERVICE_USER" -else - echo "✓ 用户 $SERVICE_USER 已存在" -fi - -# 创建安装目录 -echo "创建安装目录..." -mkdir -p "$INSTALL_DIR" -mkdir -p "$INSTALL_DIR/logs" -mkdir -p "$INSTALL_DIR/uploads" - -# 复制文件 -echo "复制服务文件..." -if [ -f "deploy/cloud-drive-server" ]; then - cp deploy/cloud-drive-server "$INSTALL_DIR/" - chmod +x "$INSTALL_DIR/cloud-drive-server" - echo "✓ 复制可执行文件" -else - echo "错误: 未找到可执行文件,请先运行打包脚本" - exit 1 -fi - -if [ -f "deploy/.env.example" ]; then - cp deploy/.env.example "$INSTALL_DIR/.env.example" - echo "✓ 复制配置文件模板" -fi - -# 设置权限 -echo "设置文件权限..." -chown -R "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR" -chmod 755 "$INSTALL_DIR" -chmod 755 "$INSTALL_DIR/cloud-drive-server" -chmod 755 "$INSTALL_DIR/logs" -chmod 755 "$INSTALL_DIR/uploads" - -# 安装systemd服务 -echo "安装systemd服务..." -cp "$SERVICE_FILE" "/etc/systemd/system/" -systemctl daemon-reload -systemctl enable "$SERVICE_NAME" -echo "✓ 服务已安装并启用" - -# 配置防火墙(如果存在) -echo "配置防火墙..." -if command -v firewall-cmd &> /dev/null; then - firewall-cmd --permanent --add-port=8000/tcp - firewall-cmd --reload - echo "✓ 防火墙配置完成 (firewalld)" -elif command -v ufw &> /dev/null; then - ufw allow 8000/tcp - echo "✓ 防火墙配置完成 (ufw)" -else - echo "注意: 未检测到防火墙管理工具,请手动开放8000端口" -fi - -# 创建日志轮转配置 -echo "配置日志轮转..." -cat > /etc/logrotate.d/cloud-drive << EOF -$INSTALL_DIR/logs/*.log { - daily - missingok - rotate 30 - compress - delaycompress - notifempty - create 644 $SERVICE_USER $SERVICE_USER - postrotate - systemctl reload cloud-drive || true - endscript -} -EOF -echo "✓ 日志轮转配置完成" - -# 提示配置 -echo "" -echo "=== 安装完成 ===" -echo "安装目录: $INSTALL_DIR" -echo "" -echo "下一步操作:" -echo "1. 编辑配置文件: nano $INSTALL_DIR/.env" -echo "2. 启动服务: systemctl start $SERVICE_NAME" -echo "3. 查看状态: systemctl status $SERVICE_NAME" -echo "4. 查看日志: journalctl -u $SERVICE_NAME -f" -echo "" -echo "服务将在以下地址提供API:" -echo "- API文档: http://$(hostname -I | awk '{print $1}'):8000/docs" -echo "- 健康检查: http://$(hostname -I | awk '{print $1}'):8000/api/v1/health" \ No newline at end of file diff --git a/backend/install_deps_root.sh b/backend/install_deps_root.sh deleted file mode 100644 index cd02f9d..0000000 --- a/backend/install_deps_root.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -# Root用户依赖安装脚本 - -echo "=== Root用户依赖安装脚本 ===" - -# 检查是否为root用户 -if [ "$EUID" -ne 0 ]; then - echo "请使用root权限运行此脚本" - echo "命令: sudo $0" - exit 1 -fi - -echo "检测到root用户,开始安装依赖..." - -# 1. 升级pip -echo "1. 升级pip..." -pip3 install --upgrade pip - -# 2. 安装email-validator -echo "2. 安装email-validator..." -pip3 install email-validator - -# 3. 安装核心依赖 -echo "3. 安装核心依赖..." -pip3 install fastapi uvicorn sqlalchemy pymysql redis python-jose passlib python-multipart pydantic pydantic-settings httpx python-dotenv loguru alembic bcrypt - -# 4. 验证安装 -echo "4. 验证安装..." -python3 -c " -import sys -packages = ['email_validator', 'fastapi', 'uvicorn', 'sqlalchemy', 'pymysql', 'redis', 'jose', 'passlib', 'pydantic', 'httpx', 'alembic'] -success = True -for pkg in packages: - try: - __import__(pkg) - print(f'✓ {pkg}') - except ImportError as e: - print(f'✗ {pkg}: {e}') - success = False - -if success: - print('\\n✓ 所有依赖安装成功!') -else: - print('\\n✗ 部分依赖安装失败') - sys.exit(1) -" - -if [ $? -eq 0 ]; then - echo "" - echo "=== 安装完成 ===" - echo "现在可以启动应用:" - echo "python3 main.py" -else - echo "安装失败,请检查错误信息" - exit 1 -fi \ No newline at end of file diff --git a/backend/install_user.sh b/backend/install_user.sh deleted file mode 100644 index 4731319..0000000 --- a/backend/install_user.sh +++ /dev/null @@ -1,154 +0,0 @@ -#!/bin/bash -# 云盘后端服务用户级安装脚本(无需sudo权限) - -set -e - -# 配置变量 -SERVICE_NAME="cloud-drive" -INSTALL_DIR="$HOME/cloud-drive" -LOG_DIR="$HOME/.local/share/cloud-drive/logs" -UPLOAD_DIR="$HOME/.local/share/cloud-drive/uploads" - -echo "=== 云盘后端服务用户级安装脚本 ===" - -# 检查系统 -if [ -f /etc/os-release ]; then - . /etc/os-release - echo "检测到系统: $NAME $VERSION" -else - echo "警告: 无法检测系统版本" -fi - -# 创建安装目录 -echo "创建安装目录..." -mkdir -p "$INSTALL_DIR" -mkdir -p "$LOG_DIR" -mkdir -p "$UPLOAD_DIR" - -# 复制文件 -echo "复制服务文件..." -if [ -f "deploy/cloud-drive-server" ]; then - cp deploy/cloud-drive-server "$INSTALL_DIR/" - chmod +x "$INSTALL_DIR/cloud-drive-server" - echo "✓ 复制可执行文件" -else - echo "错误: 未找到可执行文件,请先运行打包脚本" - exit 1 -fi - -if [ -f "deploy/.env.example" ]; then - cp deploy/.env.example "$INSTALL_DIR/.env.example" - echo "✓ 复制配置文件模板" -fi - -# 创建启动脚本 -echo "创建启动脚本..." -cat > "$INSTALL_DIR/start.sh" << EOF -#!/bin/bash -# 云盘后端服务启动脚本(用户级) - -# 设置环境变量 -export PYTHONPATH=\${PYTHONPATH}:$(dirname "$0") - -# 进入脚本所在目录 -cd "\$(dirname "$0")" - -# 检查环境文件 -if [ ! -f ".env" ]; then - echo "警告: .env 文件不存在,将使用默认配置" - if [ -f ".env.example" ]; then - cp .env.example .env - echo "已复制 .env.example 为 .env,请根据需要修改配置" - fi -fi - -# 启动服务 -echo "启动云盘后端服务..." -./cloud-drive-server -EOF - -chmod +x "$INSTALL_DIR/start.sh" -echo "✓ 创建启动脚本" - -# 创建停止脚本 -cat > "$INSTALL_DIR/stop.sh" << 'EOF' -#!/bin/bash -# 云盘后端服务停止脚本 - -echo "停止云盘后端服务..." -pkill -f cloud-drive-server || echo "服务未运行" -EOF - -chmod +x "$INSTALL_DIR/stop.sh" -echo "✓ 创建停止脚本" - -# 创建状态检查脚本 -cat > "$INSTALL_DIR/status.sh" << 'EOF' -#!/bin/bash -# 云盘后端服务状态检查脚本 - -if pgrep -f cloud-drive-server > /dev/null; then - echo "云盘后端服务正在运行" - echo "进程ID: $(pgrep -f cloud-drive-server)" - echo "端口: 8000" -else - echo "云盘后端服务未运行" -fi -EOF - -chmod +x "$INSTALL_DIR/status.sh" -echo "✓ 创建状态检查脚本" - -# 创建systemd用户服务文件(可选) -echo "创建systemd用户服务文件..." -mkdir -p "$HOME/.config/systemd/user" -cat > "$HOME/.config/systemd/user/$SERVICE_NAME.service" << EOF -[Unit] -Description=Cloud Drive Backend Service (User) -Documentation=https://github.com/your-repo/cloud-drive -After=network.target - -[Service] -Type=simple -WorkingDirectory=$INSTALL_DIR -ExecStart=$INSTALL_DIR/cloud-drive-server -Restart=always -RestartSec=10 -StandardOutput=journal -StandardError=journal -SyslogIdentifier=cloud-drive - -[Install] -WantedBy=default.target -EOF - -echo "✓ 创建systemd用户服务文件" - -# 重载systemd用户服务 -systemctl --user daemon-reload -echo "✓ systemd用户服务已加载" - -# 提示配置 -echo "" -echo "=== 用户级安装完成 ===" -echo "安装目录: $INSTALL_DIR" -echo "日志目录: $LOG_DIR" -echo "上传目录: $UPLOAD_DIR" -echo "" -echo "手动启动方式:" -echo "1. 编辑配置文件: nano $INSTALL_DIR/.env" -echo "2. 启动服务: $INSTALL_DIR/start.sh" -echo "3. 查看状态: $INSTALL_DIR/status.sh" -echo "4. 停止服务: $INSTALL_DIR/stop.sh" -echo "" -echo "systemd用户服务方式:" -echo "1. 启用服务: systemctl --user enable $SERVICE_NAME" -echo "2. 启动服务: systemctl --user start $SERVICE_NAME" -echo "3. 查看状态: systemctl --user status $SERVICE_NAME" -echo "4. 查看日志: journalctl --user -u $SERVICE_NAME -f" -echo "" -echo "服务将在以下地址提供API:" -echo "- API文档: http://localhost:8000/docs" -echo "- 健康检查: http://localhost:8000/api/v1/health" -echo "" -echo "注意: 如需绑定到特权端口(如80)或访问系统资源,请使用sudo运行install.sh" \ No newline at end of file diff --git a/backend/package-app.py b/backend/package-app.py deleted file mode 100644 index 23493ad..0000000 --- a/backend/package-app.py +++ /dev/null @@ -1,200 +0,0 @@ -#!/usr/bin/env python3 -""" -应用打包脚本 - 将Python应用打包为可执行文件 -""" - -import os -import sys -import shutil -import subprocess -from pathlib import Path - -def check_dependencies(): - """检查必要的依赖""" - try: - import PyInstaller - print("OK PyInstaller 已安装") - except ImportError: - print("正在安装 PyInstaller...") - subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller"]) - print("OK PyInstaller 安装完成") - -def create_spec_file(): - """创建 PyInstaller spec 文件""" - spec_content = ''' -# -*- mode: python ; coding: utf-8 -*- - -block_cipher = None - -a = Analysis( - ['main.py'], - pathex=[], - binaries=[], - datas=[ - ('app', 'app'), - ('uploads', 'uploads'), - ('logs', 'logs'), - ], - hiddenimports=[ - 'uvicorn', - 'fastapi', - 'sqlalchemy', - 'pymysql', - 'pydantic', - 'pydantic_settings', - 'redis', - 'passlib', - 'python_jose', - 'uvicorn.protocols.http.httptools_impl', - ], - hookspath=[], - hooksconfig={}, - runtime_hooks=[], - excludes=[], - win_no_prefer_redirects=False, - win_private_assemblies=False, - cipher=block_cipher, - noarchive=False, -) - -pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) - -exe = EXE( - pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, - [], - name='cloud-drive-server', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - upx_exclude=[], - runtime_tmpdir=None, - console=True, - disable_windowed_traceback=False, - argv_emulation=False, - target_arch=None, - codesign_identity=None, - entitlements_file=None, - icon=None -) -''' - - with open('cloud-drive-server.spec', 'w', encoding='utf-8') as f: - f.write(spec_content) - print("OK 创建了 cloud-drive-server.spec 文件") - -def build_executable(): - """构建可执行文件""" - print("开始构建可执行文件...") - - try: - # 使用 PyInstaller 构建 - result = subprocess.run([ - sys.executable, '-m', 'PyInstaller', - '--clean', - '--noconfirm', - 'cloud-drive-server.spec' - ], capture_output=True, text=True) - - if result.returncode == 0: - print("OK 可执行文件构建成功") - print("输出目录: dist/") - return True - else: - print("ERROR 构建失败:") - print(result.stdout) - print(result.stderr) - return False - - except Exception as e: - print(f"ERROR 构建过程中出现错误: {e}") - return False - -def create_dockerfile_for_executable(): - """为可执行文件创建最小化的 Dockerfile""" - dockerfile_content = '''# 最小化运行环境 - 使用可执行文件 -FROM alpine:latest - -# 安装运行时依赖 -RUN apk add --no-cache \\ - curl \\ - tzdata \\ - ca-certificates \\ - && rm -rf /var/cache/apk/* - -# 设置时区 -ENV TZ=Asia/Shanghai -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -# 创建应用用户 -RUN adduser -D -s /bin/sh app - -# 设置工作目录 -WORKDIR /app - -# 复制可执行文件 -COPY dist/cloud-drive-server /app/cloud-drive-server - -# 创建必要的目录 -RUN mkdir -p /app/uploads /app/logs \\ - && chown -R app:app /app - -# 切换到非root用户 -USER app - -# 暴露端口 -EXPOSE 8002 - -# 健康检查 -HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \\ - CMD curl -f http://localhost:8002/api/v1/health || exit 1 - -# 启动命令 -CMD ["./cloud-drive-server"] -''' - - with open('Dockerfile.executable', 'w', encoding='utf-8') as f: - f.write(dockerfile_content) - print("OK 创建了 Dockerfile.executable 文件") - -def main(): - """主函数""" - print("=== 云盘应用打包工具 ===") - print("正在将应用打包为Docker镜像...") - - # 检查当前目录 - if not Path('main.py').exists(): - print("ERROR 错误: 在当前目录未找到 main.py 文件") - print("请在 backend 目录中运行此脚本") - return False - - # 检查依赖 - check_dependencies() - - # 创建 spec 文件 - create_spec_file() - - # 构建可执行文件 - if not build_executable(): - return False - - # 创建可执行文件的 Dockerfile - create_dockerfile_for_executable() - - print("\n=== 打包完成 ===") - print("OK 应用已成功打包") - print("OK 可执行文件位于: dist/cloud-drive-server") - print("OK Dockerfile: Dockerfile.executable") - print("\n下一步命令:") - print(" docker build -f Dockerfile.executable -t cloud-drive-backend:latest .") - print(" docker run -d -p 8002:8002 --name cloud-drive-backend cloud-drive-backend:latest") - - return True - -if __name__ == "__main__": - success = main() - sys.exit(0 if success else 1) \ No newline at end of file diff --git a/backend/prepare_linux_package.sh b/backend/prepare_linux_package.sh deleted file mode 100644 index 8cc88f0..0000000 --- a/backend/prepare_linux_package.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash -# 准备Linux打包的源代码包 - -echo "=== 准备Linux打包源代码包 ===" - -# 创建临时目录 -PACKAGE_DIR="cloud-drive-source-$(date +%Y%m%d)" -mkdir -p "$PACKAGE_DIR" - -# 复制必要文件 -echo "复制源代码..." -cp -r app/ "$PACKAGE_DIR/" -cp main.py "$PACKAGE_DIR/" -cp build.spec "$PACKAGE_DIR/" -cp build_linux.py "$PACKAGE_DIR/" -cp requirements.txt "$PACKAGE_DIR/" -cp requirements-build.txt "$PACKAGE_DIR/" -cp .env.example "$PACKAGE_DIR/" -cp cloud-drive.service "$PACKAGE_DIR/" -cp install.sh "$PACKAGE_DIR/" -cp uninstall.sh "$PACKAGE_DIR/" -cp BUILD_GUIDE.md "$PACKAGE_DIR/" - -# 创建Linux打包脚本 -cat > "$PACKAGE_DIR/build_on_linux.sh" << 'EOF' -#!/bin/bash -# 在Linux环境下的打包脚本 - -echo "=== 在Linux环境下打包云盘后端 ===" - -# 安装系统依赖 -sudo apt-get update -sudo apt-get install -y python3 python3-pip python3-venv build-essential - -# 创建虚拟环境 -python3 -m venv venv -source venv/bin/activate - -# 安装依赖 -pip install --upgrade pip -pip install -r requirements-build.txt -pip install -r requirements.txt - -# 运行打包 -python build_linux.py - -echo "=== 打包完成 ===" -echo "可执行文件位置: deploy/cloud-drive-server" -echo "现在可以运行 ./install.sh 进行安装" -EOF - -chmod +x "$PACKAGE_DIR/build_on_linux.sh" - -# 创建压缩包 -echo "创建压缩包..." -tar -czf "$PACKAGE_DIR.tar.gz" "$PACKAGE_DIR" - -echo "=== 源代码包准备完成 ===" -echo "生成的文件:" -echo " $PACKAGE_DIR/ - 源代码目录" -echo " $PACKAGE_DIR.tar.gz - 压缩包" -echo "" -echo "将压缩包上传到Linux服务器后,解压并运行:" -echo " tar -xzf $PACKAGE_DIR.tar.gz" -echo " cd $PACKAGE_DIR" -echo " ./build_on_linux.sh" \ No newline at end of file diff --git a/backend/prepare_linux_package_fixed.sh b/backend/prepare_linux_package_fixed.sh deleted file mode 100644 index 6615f90..0000000 --- a/backend/prepare_linux_package_fixed.sh +++ /dev/null @@ -1,229 +0,0 @@ -#!/bin/bash -# 准备Linux打包的源代码包(修复版) - -echo "=== 准备Linux打包源代码包(修复版) ===" - -# 删除旧的包 -rm -rf cloud-drive-source-* - -# 创建临时目录 -PACKAGE_DIR="cloud-drive-source-$(date +%Y%m%d-%H%M%S)" -mkdir -p "$PACKAGE_DIR" - -echo "复制源代码和配置文件..." -# 复制必要文件 -cp -r app/ "$PACKAGE_DIR/" -cp main.py "$PACKAGE_DIR/" -cp build.spec "$PACKAGE_DIR/" -cp build_linux_fixed.py "$PACKAGE_DIR/build_linux.py" -cp requirements.txt "$PACKAGE_DIR/" -cp requirements-build.txt "$PACKAGE_DIR/" -cp .env.example "$PACKAGE_DIR/" -cp cloud-drive.service "$PACKAGE_DIR/" -cp install.sh "$PACKAGE_DIR/" -cp install_user.sh "$PACKAGE_DIR/" -cp BUILD_GUIDE.md "$PACKAGE_DIR/" - -# 创建Linux打包脚本 -cat > "$PACKAGE_DIR/build_on_linux.sh" << 'EOF' -#!/bin/bash -# 在Linux环境下的打包脚本(修复版) - -echo "=== 在Linux环境下打包云盘后端(修复版) ===" - -# 检查是否为root用户 -if [ "$EUID" -eq 0 ]; then - echo "警告: 不建议在root用户下直接打包,建议使用普通用户" - read -p "是否继续?(y/N): " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - exit 1 - fi -fi - -# 安装系统依赖(Ubuntu/Debian) -if command -v apt-get &> /dev/null; then - echo "检测到Ubuntu/Debian系统" - sudo apt-get update || echo "无法更新包列表,跳过..." - sudo apt-get install -y python3 python3-pip python3-venv build-essential || echo "安装系统依赖失败,请手动安装" -# 安装系统依赖(CentOS/RHEL) -elif command -v yum &> /dev/null; then - echo "检测到CentOS/RHEL系统" - sudo yum install -y python3 python3-pip python3-devel gcc gcc-c++ make || echo "安装系统依赖失败,请手动安装" -# 安装系统依赖(其他系统) -else - echo "警告: 未检测到支持的包管理器,请手动安装Python3和编译工具" -fi - -# 检查Python版本 -python3 --version -if [ $? -ne 0 ]; then - echo "错误: Python3 未安装或无法访问" - exit 1 -fi - -# 创建虚拟环境 -echo "创建Python虚拟环境..." -python3 -m venv venv || { - echo "错误: 创建虚拟环境失败" - exit 1 -} - -# 激活虚拟环境 -echo "激活虚拟环境..." -source venv/bin/activate || { - echo "错误: 激活虚拟环境失败" - exit 1 -} - -# 升级pip -echo "升级pip..." -pip install --upgrade pip - -# 安装依赖 -echo "安装Python依赖包..." -pip install -r requirements-build.txt || { - echo "错误: 安装构建依赖失败" - exit 1 -} - -pip install -r requirements.txt || { - echo "错误: 安装应用依赖失败" - exit 1 -} - -# 运行打包 -echo "开始打包..." -python build_linux.py || { - echo "错误: 打包失败" - exit 1 -} - -# 检查打包结果 -if [ -f "deploy/cloud-drive-server" ]; then - echo "=== 打包成功 ===" - echo "可执行文件位置: deploy/cloud-drive-server" - echo "文件大小: $(ls -lh deploy/cloud-drive-server | awk '{print $5}')" - echo "" - echo "下一步操作:" - echo "1. 用户级安装(推荐,无需sudo):" - echo " cd deploy && ./install_user.sh" - echo "" - echo "2. 系统级安装(需要sudo权限):" - echo " cd deploy && sudo ./install.sh" - echo "" - echo "3. 直接运行:" - echo " cd deploy && ./cloud-drive-server" - echo "" - echo "4. 查看详细说明:" - echo " cat deploy/README.md" -else - echo "错误: 打包失败,未找到可执行文件" - exit 1 -fi -EOF - -chmod +x "$PACKAGE_DIR/build_on_linux.sh" - -# 创建问题排查脚本 -cat > "$PACKAGE_DIR/troubleshoot.sh" << 'EOF' -#!/bin/bash -# 问题排查脚本 - -echo "=== 云盘后端问题排查工具 ===" - -echo "1. 检查Python环境:" -python3 --version 2>&1 || echo "Python3 未安装" - -echo "" -echo "2. 检查pip:" -pip3 --version 2>&1 || echo "pip3 未安装" - -echo "" -echo "3. 检查系统依赖:" -if command -v apt-get &> /dev/null; then - echo "包管理器: apt-get (Ubuntu/Debian)" - dpkg -l | grep -E "(python3|gcc|make)" || echo "检查系统依赖包..." -elif command -v yum &> /dev/null; then - echo "包管理器: yum (CentOS/RHEL)" - rpm -qa | grep -E "(python3|gcc|make)" || echo "检查系统依赖包..." -else - echo "未检测到支持的包管理器" -fi - -echo "" -echo "4. 检查虚拟环境:" -if [ -d "venv" ]; then - echo "虚拟环境目录存在" - if [ -f "venv/bin/python" ]; then - echo "虚拟环境Python可执行文件存在" - venv/bin/python --version - else - echo "虚拟环境Python可执行文件不存在" - fi -else - echo "虚拟环境目录不存在" -fi - -echo "" -echo "5. 检查源代码文件:" -for file in main.py build.spec requirements.txt; do - if [ -f "$file" ]; then - echo "✓ $file 存在" - else - echo "✗ $file 不存在" - fi -done - -echo "" -echo "6. 检查app目录:" -if [ -d "app" ]; then - echo "✓ app目录存在" - find app -name "*.py" | head -5 | while read file; do - echo " ✓ $file" - done -else - echo "✗ app目录不存在" -fi - -echo "" -echo "7. 网络连接测试:" -if ping -c 1 pypi.org &> /dev/null; then - echo "✓ 可以访问PyPI" -else - echo "✗ 无法访问PyPI,可能需要配置代理" -fi - -echo "" -echo "=== 排查完成 ===" -echo "如果发现问题,请根据上述输出进行修复" -EOF - -chmod +x "$PACKAGE_DIR/troubleshoot.sh" - -# 创建压缩包 -echo "创建压缩包..." -tar -czf "$PACKAGE_DIR.tar.gz" "$PACKAGE_DIR" - -echo "=== 源代码包准备完成 ===" -echo "生成的文件:" -echo " $PACKAGE_DIR/ - 源代码目录" -echo " $PACKAGE_DIR.tar.gz - 压缩包 ($(ls -lh "$PACKAGE_DIR.tar.gz" | awk '{print $5}'))" -echo "" -echo "修复内容:" -echo " ✓ 添加了用户级安装脚本 install_user.sh" -echo " ✓ 修复了 build.spec 依赖缺失问题" -echo " ✓ 改进了打包脚本 build_linux.py" -echo " ✓ 添加了问题排查脚本 troubleshoot.sh" -echo " ✓ 增强了安装说明文档" -echo "" -echo "将压缩包上传到Linux服务器后,解压并运行:" -echo " tar -xzf $PACKAGE_DIR.tar.gz" -echo " cd $PACKAGE_DIR" -echo " ./build_on_linux.sh" -echo "" -echo "如果遇到问题,可以先运行:" -echo " ./troubleshoot.sh" -EOF - -chmod +x backend/prepare_linux_package_fixed.sh \ No newline at end of file diff --git a/backend/quick_build.sh b/backend/quick_build.sh deleted file mode 100644 index 6940705..0000000 --- a/backend/quick_build.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# 快速打包脚本 - Linux环境 - -echo "=== 云盘后端快速打包脚本 ===" - -# 检查Python环境 -if ! command -v python3 &> /dev/null; then - echo "错误: 未找到Python3" - exit 1 -fi - -echo "Python版本: $(python3 --version)" - -# 安装PyInstaller -echo "安装PyInstaller..." -pip3 install pyinstaller - -# 安装项目依赖 -echo "安装项目依赖..." -pip3 install -r requirements.txt - -# 运行打包 -echo "开始打包..." -python3 build_linux.py - -echo "=== 打包完成 ===" -echo "部署包位置: ./deploy/" -echo "请查看 ./deploy/README.md 了解部署说明" \ No newline at end of file diff --git a/backend/quick_db_fix.sh b/backend/quick_db_fix.sh deleted file mode 100644 index a2c5b66..0000000 --- a/backend/quick_db_fix.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# 快速数据库连接修复 - -echo "=== 快速数据库连接修复 ===" - -# 检查.env文件并修复数据库URL -if [ -f ".env" ]; then - echo "修复 .env 文件中的数据库配置..." - - # 备份原文件 - cp .env .env.backup.$(date +%Y%m%d_%H%M%S) - - # 更新数据库URL为外部数据库 - sed -i 's|DATABASE_URL=.*|DATABASE_URL=mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db|' .env - - echo "✓ 数据库配置已更新为外部数据库" -else - echo "创建 .env 文件..." - cat > .env << EOF -DATABASE_URL=mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db -EOF - echo "✓ .env 文件已创建" -fi - -echo "" -echo "请重启应用以使配置生效" -echo "重启命令: python main.py" \ No newline at end of file diff --git a/backend/quick_fix_server.py b/backend/quick_fix_server.py deleted file mode 100644 index 04513af..0000000 --- a/backend/quick_fix_server.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -服务器端快速修复脚本 -修复PyInstaller打包时的database目录缺失问题 -""" - -import os -from pathlib import Path - -def fix_build_spec(): - """修复build.spec文件,处理可选数据文件""" - spec_file = Path('build.spec') - - if not spec_file.exists(): - print("错误: build.spec 文件不存在") - return False - - # 读取原文件内容 - with open(spec_file, 'r', encoding='utf-8') as f: - content = f.read() - - # 查找并替换datas部分 - old_datas = '''# 需要包含的数据文件 -datas = [ - (str(ROOT_DIR / 'app'), 'app'), # 包含整个app目录 - ('.env.example', '.'), # 包含环境配置示例文件 - ('database', 'database'), # 包含数据库相关文件 -]''' - - new_datas = '''# 需要包含的数据文件 -datas = [ - (str(ROOT_DIR / 'app'), 'app'), # 包含整个app目录 - ('.env.example', '.'), # 包含环境配置示例文件 -] - -# 可选数据文件(如果存在才包含) -optional_files = [ - ('database', 'database'), # 包含数据库相关文件 -] - -# 添加可选数据文件 -for src, dst in optional_files: - src_path = ROOT_DIR / src - if src_path.exists(): - datas.append((src, dst)) - print(f"包含可选数据文件: {src}") - else: - print(f"跳过可选数据文件: {src} (不存在)")''' - - if old_datas in content: - content = content.replace(old_datas, new_datas) - - # 写回文件 - with open(spec_file, 'w', encoding='utf-8') as f: - f.write(content) - - print("✓ 已修复 build.spec 文件") - return True - else: - print("build.spec 文件已经包含修复或格式不匹配") - return False - -def create_database_dir(): - """创建database目录(如果不存在)""" - db_dir = Path('database') - - if not db_dir.exists(): - db_dir.mkdir(exist_ok=True) - - # 创建一个空的初始化文件 - init_file = db_dir / 'init' / '.gitkeep' - init_file.parent.mkdir(exist_ok=True) - init_file.touch() - - # 创建一个说明文件 - readme_file = db_dir / 'README.md' - with open(readme_file, 'w', encoding='utf-8') as f: - f.write("""# Database目录 - -此目录包含数据库相关的初始化脚本和配置文件。 - -## 文件说明 - -- `init/`: 数据库初始化脚本目录 -- `create_files_table.py`: 创建文件表的脚本 - -## 注意 - -如果此目录为空,不会影响应用的正常运行。应用会自动创建所需的数据库表。 -""") - - print("✓ 已创建 database 目录") - return True - else: - print("✓ database 目录已存在") - return True - -def main(): - """主函数""" - print("=== 服务器端快速修复脚本 ===") - - # 修复build.spec文件 - print("1. 修复 build.spec 文件...") - fix_build_spec() - - # 创建database目录 - print("\n2. 检查 database 目录...") - create_database_dir() - - print("\n=== 修复完成 ===") - print("现在可以重新运行打包:") - print("python build_linux.py") - - # 验证修复结果 - print("\n=== 验证修复结果 ===") - - if Path('build.spec').exists(): - print("✓ build.spec 文件存在") - else: - print("✗ build.spec 文件不存在") - - if Path('database').exists(): - print("✓ database 目录存在") - files = list(Path('database').rglob('*')) - print(f" 包含 {len(files)} 个文件/目录") - else: - print("✗ database 目录不存在") - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/backend/quick_start_project.py b/backend/quick_start_project.py deleted file mode 100644 index 4fee35b..0000000 --- a/backend/quick_start_project.py +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -快速启动和恢复脚本 -""" - -import os -import sys -import subprocess -from pathlib import Path - -def check_python_version(): - """检查Python版本""" - if sys.version_info < (3, 8): - print("错误: 需要Python 3.8或更高版本") - return False - print(f"✓ Python版本: {sys.version}") - return True - -def check_virtual_env(): - """检查虚拟环境""" - venv_path = Path('venv') - if venv_path.exists(): - print("✓ 虚拟环境存在") - return True - else: - print("✗ 虚拟环境不存在,正在创建...") - try: - subprocess.run([sys.executable, '-m', 'venv', 'venv'], check=True) - print("✓ 虚拟环境创建成功") - return True - except subprocess.CalledProcessError: - print("✗ 虚拟环境创建失败") - return False - -def activate_virtual_env(): - """激活虚拟环境""" - if sys.platform == "win32": - activate_script = Path('venv/Scripts/activate') - else: - activate_script = Path('venv/bin/activate') - - if activate_script.exists(): - print("✓ 虚拟环境激活脚本存在") - return True - else: - print("✗ 虚拟环境激活脚本不存在") - return False - -def install_dependencies(): - """安装依赖""" - print("安装依赖包...") - - if sys.platform == "win32": - pip_path = 'venv/Scripts/pip' - python_path = 'venv/Scripts/python' - else: - pip_path = 'venv/bin/pip' - python_path = 'venv/bin/python' - - # 升级pip - try: - subprocess.run([python_path, '-m', 'pip', 'install', '--upgrade', 'pip'], check=True) - print("✓ pip升级成功") - except subprocess.CalledProcessError: - print("✗ pip升级失败") - - # 安装基础依赖 - basic_packages = [ - 'fastapi==0.104.1', - 'uvicorn[standard]==0.24.0', - 'sqlalchemy==2.0.23', - 'pymysql==1.1.0', - 'python-jose[cryptography]==3.3.0', - 'passlib[bcrypt]==1.7.4', - 'python-multipart==0.0.6', - 'pydantic==2.5.0', - 'pydantic-settings==2.1.0', - 'httpx==0.25.2', - 'python-dotenv==1.0.0', - 'loguru>=0.7.0' - ] - - try: - for package in basic_packages: - print(f"安装 {package}...") - subprocess.run([pip_path, 'install', package], check=True) - print("✓ 依赖安装成功") - return True - except subprocess.CalledProcessError as e: - print(f"✗ 依赖安装失败: {e}") - return False - -def create_basic_app_structure(): - """创建基本的app结构""" - print("创建基本app结构...") - - # 创建目录 - directories = [ - 'app', - 'app/core', - 'app/api/v1/endpoints' - ] - - for dir_path in directories: - Path(dir_path).mkdir(parents=True, exist_ok=True) - print(f"✓ 创建目录: {dir_path}") - - # 创建__init__.py文件 - init_files = [ - ('app/__init__.py', '"""云盘应用包"""\n'), - ('app/core/__init__.py', '"""核心模块包"""\n'), - ('app/api/__init__.py', '"""API模块包"""\n'), - ('app/api/v1/__init__.py', '"""API v1模块包"""\n'), - ('app/api/v1/endpoints/__init__.py', '"""API端点模块包"""\n') - ] - - for file_path, content in init_files: - full_path = Path(file_path) - if not full_path.exists(): - full_path.write_text(content, encoding='utf-8') - print(f"✓ 创建文件: {file_path}") - -def create_essential_files(): - """创建必要的文件""" - print("创建必要的文件...") - - # app/core/config.py - config_content = '''from pydantic_settings import BaseSettings -from typing import List - -class Settings(BaseSettings): - ENVIRONMENT: str = "development" - DEBUG: bool = True - DATABASE_URL: str = "mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db" - REDIS_URL: str = "redis://localhost:6379" - JWT_SECRET_KEY: str = "your-super-secret-jwt-key-change-in-production" - JWT_ALGORITHM: str = "HS256" - JWT_EXPIRE_MINUTES: int = 30 - ALLOWED_HOSTS: List[str] = ["*"] - MAX_FILE_SIZE: int = 10 * 1024 * 1024 - UPLOAD_DIR: str = "uploads" - - class Config: - env_file = ".env" - case_sensitive = True - -settings = Settings() -''' - - Path('app/core/config.py').write_text(config_content, encoding='utf-8') - print("✓ 创建 app/core/config.py") - - # app/api/v1/endpoints/health.py - health_content = '''from fastapi import APIRouter -from datetime import datetime - -router = APIRouter() - -@router.get("/health") -async def health_check(): - return { - "status": "healthy", - "timestamp": datetime.utcnow(), - "version": "1.0.0" - } - -@router.get("/") -async def root(): - return { - "message": "云盘应用 API", - "version": "1.0.0", - "docs": "/docs" - } -''' - - Path('app/api/v1/endpoints/health.py').write_text(health_content, encoding='utf-8') - print("✓ 创建 app/api/v1/endpoints/health.py") - -def create_simple_main(): - """创建简化的main.py""" - print("创建简化的main.py...") - - main_content = '''import os -import sys -from pathlib import Path - -# 添加当前目录到Python路径 -current_dir = Path(__file__).parent -sys.path.insert(0, str(current_dir)) - -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware -from app.core.config import settings -from app.api.v1.endpoints import health - -app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" -) - -# CORS中间件 -app.add_middleware( - CORSMiddleware, - allow_origins=settings.ALLOWED_HOSTS, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -# 包含路由 -app.include_router(health.router, prefix="/api/v1", tags=["health"]) - -if __name__ == "__main__": - import uvicorn - print("启动云盘后端服务...") - print("访问地址: http://localhost:8000") - print("API文档: http://localhost:8000/docs") - - uvicorn.run( - app, - host="0.0.0.0", - port=8000, - reload=False - ) -''' - - Path('main.py').write_text(main_content, encoding='utf-8') - print("✓ 创建 main.py") - -def start_project(): - """启动项目""" - print("启动项目...") - - if sys.platform == "win32": - python_path = 'venv/Scripts/python' - else: - python_path = 'venv/bin/python' - - try: - # 直接运行main.py - subprocess.run([python_path, 'main.py'], check=True) - except subprocess.CalledProcessError as e: - print(f"启动失败: {e}") - return False - except KeyboardInterrupt: - print("服务已停止") - return True - -def main(): - """主函数""" - print("=== 云盘后端快速启动脚本 ===") - - # 检查Python版本 - if not check_python_version(): - return - - # 检查和创建虚拟环境 - if not check_virtual_env(): - print("虚拟环境创建失败") - return - - # 安装依赖 - if not install_dependencies(): - print("依赖安装失败") - return - - # 创建基本结构 - create_basic_app_structure() - - # 创建必要文件 - create_essential_files() - - # 创建简化main.py - create_simple_main() - - # 创建日志和上传目录 - Path('logs').mkdir(exist_ok=True) - Path('uploads').mkdir(exist_ok=True) - - print("\n=== 准备完成 ===") - print("现在启动项目...") - - # 启动项目 - start_project() - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/backend/recreate_app_structure.py b/backend/recreate_app_structure.py deleted file mode 100644 index ffb41c4..0000000 --- a/backend/recreate_app_structure.py +++ /dev/null @@ -1,491 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -重新创建完整的app目录结构和文件 -""" - -import os -from pathlib import Path - -def create_app_directory(): - """创建app目录结构""" - print("=== 创建app目录结构 ===") - - base_dir = Path('.') - - # 创建主要目录结构 - directories = [ - 'app', - 'app/core', - 'app/api', - 'app/api/v1', - 'app/api/v1/endpoints', - 'app/models', - 'app/schemas', - 'app/services', - 'app/utils' - ] - - for dir_path in directories: - full_path = base_dir / dir_path - full_path.mkdir(parents=True, exist_ok=True) - print(f"✓ 创建目录: {dir_path}") - -def create_init_files(): - """创建__init__.py文件""" - print("\n=== 创建__init__.py文件 ===") - - base_dir = Path('.') - - # 各目录的__init__.py内容 - init_contents = { - 'app/__init__.py': '"""云盘应用包"""\n\n__version__ = "1.0.0"\n', - 'app/core/__init__.py': '"""核心模块包"""\n', - 'app/api/__init__.py': '"""API模块包"""\n', - 'app/api/v1/__init__.py': '"""API v1模块包"""\n', - 'app/api/v1/endpoints/__init__.py': '"""API端点模块包"""\n', - 'app/models/__init__.py': '"""数据模型包"""\n', - 'app/schemas/__init__.py': '"""Pydantic模式包"""\n', - 'app/services/__init__.py': '"""业务逻辑服务包"""\n', - 'app/utils/__init__.py': '"""工具函数包"""\n' - } - - for file_path, content in init_contents.items(): - full_path = base_dir / file_path - if not full_path.exists(): - full_path.write_text(content, encoding='utf-8') - print(f"✓ 创建文件: {file_path}") - -def create_core_files(): - """创建核心文件""" - print("\n=== 创建核心文件 ===") - - base_dir = Path('.') - - # app/core/config.py - config_content = '''from pydantic_settings import BaseSettings -from typing import List -import os - -class Settings(BaseSettings): - # 基础配置 - ENVIRONMENT: str = "development" - DEBUG: bool = True - - # 数据库配置 - DATABASE_URL: str = "mysql+pymysql://mytest_db:mytest_db@101.126.85.76:3306/mytest_db" - - # Redis配置 - REDIS_URL: str = "redis://localhost:6379" - - # JWT配置 - JWT_SECRET_KEY: str = "your-super-secret-jwt-key-change-in-production" - JWT_ALGORITHM: str = "HS256" - JWT_EXPIRE_MINUTES: int = 30 - JWT_REFRESH_EXPIRE_DAYS: int = 7 - - # CORS配置 - ALLOWED_HOSTS: List[str] = [ - "http://localhost:3000", - "http://localhost:3001", - "http://localhost:3002", - "http://localhost:3003", - "http://localhost:3004", - "http://127.0.0.1:3000", - "http://127.0.0.1:3001", - "http://127.0.0.1:3002", - "http://127.0.0.1:3003", - "http://127.0.0.1:3004", - "http://172.16.16.89:3000", - "http://172.16.16.89:3001", - "http://172.16.16.89:3002", - "http://172.16.16.89:3003", - "http://172.16.16.89:3004", - "*" - ] - - # 文件上传配置 - MAX_FILE_SIZE: int = 10 * 1024 * 1024 # 10MB - UPLOAD_DIR: str = "uploads" - ALLOWED_EXTENSIONS: List[str] = [ - # 图片 - ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg", - # 文档 - ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", - ".txt", ".rtf", ".csv", - # 压缩文件 - ".zip", ".rar", ".7z", ".tar", ".gz", - # 音频 - ".mp3", ".wav", ".flac", ".aac", ".ogg", - # 视频 - ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", - # 代码文件 - ".py", ".js", ".html", ".css", ".json", ".xml", ".yaml", ".yml", - ".java", ".cpp", ".c", ".h", ".cs", ".php", ".rb", ".go", - ".sql", ".sh", ".bat", ".ps1", ".md", ".log" - ] - - # 安全配置 - BCRYPT_ROUNDS: int = 12 - - class Config: - env_file = ".env" - case_sensitive = True - -settings = Settings() -''' - - config_file = base_dir / 'app' / 'core' / 'config.py' - config_file.write_text(config_content, encoding='utf-8') - print("✓ 创建 app/core/config.py") - - # app/core/database.py - database_content = '''from sqlalchemy import create_engine -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import sessionmaker -from app.core.config import settings - -# 创建数据库引擎 -engine = create_engine( - settings.DATABASE_URL, - pool_pre_ping=True, - pool_recycle=300, -) - -# 创建会话工厂 -SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) - -# 创建Base类 -Base = declarative_base() - -def get_db(): - """获取数据库会话""" - db = SessionLocal() - try: - yield db - finally: - db.close() -''' - - database_file = base_dir / 'app' / 'core' / 'database.py' - database_file.write_text(database_content, encoding='utf-8') - print("✓ 创建 app/core/database.py") - - # app/core/security.py - security_content = '''from datetime import datetime, timedelta -from typing import Optional -from jose import JWTError, jwt -from passlib.context import CryptContext -from app.core.config import settings - -# 密码加密上下文 -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") - -def verify_password(plain_password: str, hashed_password: str) -> bool: - """验证密码""" - return pwd_context.verify(plain_password, hashed_password) - -def get_password_hash(password: str) -> str: - """获取密码哈希""" - return pwd_context.hash(password) - -def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): - """创建访问令牌""" - to_encode = data.copy() - if expires_delta: - expire = datetime.utcnow() + expires_delta - else: - expire = datetime.utcnow() + timedelta(minutes=settings.JWT_EXPIRE_MINUTES) - - to_encode.update({"exp": expire}) - encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM) - return encoded_jwt - -def verify_token(token: str): - """验证令牌""" - try: - payload = jwt.decode(token, settings.JWT_SECRET_KEY, algorithms=[settings.JWT_ALGORITHM]) - return payload - except JWTError: - return None -''' - - security_file = base_dir / 'app' / 'core' / 'security.py' - security_file.write_text(security_content, encoding='utf-8') - print("✓ 创建 app/core/security.py") - -def create_api_files(): - """创建API文件""" - print("\n=== 创建API文件 ===") - - base_dir = Path('.') - - # app/api/v1/endpoints/health.py - health_content = '''from fastapi import APIRouter, status -from datetime import datetime - -router = APIRouter() - -@router.get("/health", status_code=status.HTTP_200_OK) -async def health_check(): - """健康检查端点""" - return { - "status": "healthy", - "timestamp": datetime.utcnow(), - "version": "1.0.0", - "message": "云盘后端服务运行正常" - } - -@router.get("/") -async def root(): - """根端点""" - return { - "message": "云盘应用 API", - "version": "1.0.0", - "docs": "/docs", - "health": "/api/v1/health" - } -''' - - health_file = base_dir / 'app' / 'api' / 'v1' / 'endpoints' / 'health.py' - health_file.write_text(health_content, encoding='utf-8') - print("✓ 创建 app/api/v1/endpoints/health.py") - - # app/api/v1/endpoints/auth.py - auth_content = '''from fastapi import APIRouter, Depends, HTTPException, status -from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -from sqlalchemy.orm import Session -from typing import Optional -from datetime import timedelta - -from app.core.database import get_db -from app.core.security import verify_password, create_access_token -from app.core.config import settings -from app.schemas.user import UserCreate, UserResponse, Token - -router = APIRouter() -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/v1/auth/token") - -@router.post("/register", response_model=UserResponse) -async def register(user_data: UserCreate, db: Session = Depends(get_db)): - """用户注册""" - # TODO: 实现用户注册逻辑 - return {"message": "注册功能待实现"} - -@router.post("/token", response_model=Token) -async def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)): - """用户登录""" - # TODO: 实现用户登录逻辑 - return { - "access_token": "dummy_token", - "token_type": "bearer", - "expires_in": settings.JWT_EXPIRE_MINUTES * 60 - } - -@router.get("/me", response_model=UserResponse) -async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)): - """获取当前用户信息""" - # TODO: 实现获取当前用户逻辑 - return {"message": "用户信息功能待实现"} -''' - - auth_file = base_dir / 'app' / 'api' / 'v1' / 'endpoints' / 'auth.py' - auth_file.write_text(auth_content, encoding='utf-8') - print("✓ 创建 app/api/v1/endpoints/auth.py") - - # app/api/v1/endpoints/files.py - files_content = '''from fastapi import APIRouter, Depends, HTTPException, UploadFile, File -from sqlalchemy.orm import Session -from typing import List - -from app.core.database import get_db -from app.schemas.file import FileResponse, FileUploadResponse - -router = APIRouter() - -@router.post("/upload", response_model=FileUploadResponse) -async def upload_file( - file: UploadFile = File(...), - db: Session = Depends(get_db) -): - """上传文件""" - # TODO: 实现文件上传逻辑 - return { - "message": "文件上传功能待实现", - "filename": file.filename, - "size": 0 - } - -@router.get("/list", response_model=List[FileResponse]) -async def list_files( - skip: int = 0, - limit: int = 100, - db: Session = Depends(get_db) -): - """获取文件列表""" - # TODO: 实现文件列表逻辑 - return [] - -@router.get("/{file_id}", response_model=FileResponse) -async def get_file_info(file_id: int, db: Session = Depends(get_db)): - """获取文件信息""" - # TODO: 实现获取文件信息逻辑 - return {"message": "文件信息功能待实现"} - -@router.delete("/{file_id}") -async def delete_file(file_id: int, db: Session = Depends(get_db)): - """删除文件""" - # TODO: 实现文件删除逻辑 - return {"message": "文件删除功能待实现"} -''' - - files_file = base_dir / 'app' / 'api' / 'v1' / 'endpoints' / 'files.py' - files_file.write_text(files_content, encoding='utf-8') - print("✓ 创建 app/api/v1/endpoints/files.py") - -def create_schema_files(): - """创建Pydantic模式文件""" - print("\n=== 创建模式文件 ===") - - base_dir = Path('.') - - # app/schemas/user.py - user_schema_content = '''from pydantic import BaseModel, EmailStr -from typing import Optional - -class UserBase(BaseModel): - username: str - email: EmailStr - -class UserCreate(UserBase): - password: str - confirm_password: str - -class UserUpdate(BaseModel): - username: Optional[str] = None - email: Optional[EmailStr] = None - -class UserResponse(UserBase): - id: int - is_active: bool - created_at: str - - class Config: - from_attributes = True - -class Token(BaseModel): - access_token: str - token_type: str - expires_in: int -''' - - user_schema_file = base_dir / 'app' / 'schemas' / 'user.py' - user_schema_file.write_text(user_schema_content, encoding='utf-8') - print("✓ 创建 app/schemas/user.py") - - # app/schemas/file.py - file_schema_content = '''from pydantic import BaseModel -from typing import Optional -from datetime import datetime - -class FileBase(BaseModel): - filename: str - original_filename: str - file_size: int - content_type: str - -class FileCreate(FileBase): - pass - -class FileUpdate(BaseModel): - filename: Optional[str] = None - -class FileResponse(FileBase): - id: int - user_id: int - file_path: str - created_at: datetime - - class Config: - from_attributes = True - -class FileUploadResponse(BaseModel): - message: str - filename: str - size: int - file_id: Optional[int] = None -''' - - file_schema_file = base_dir / 'app' / 'schemas' / 'file.py' - file_schema_file.write_text(file_schema_content, encoding='utf-8') - print("✓ 创建 app/schemas/file.py") - -def verify_structure(): - """验证项目结构""" - print("\n=== 验证项目结构 ===") - - base_dir = Path('.') - - required_files = [ - 'app/__init__.py', - 'app/core/__init__.py', - 'app/core/config.py', - 'app/core/database.py', - 'app/core/security.py', - 'app/api/__init__.py', - 'app/api/v1/__init__.py', - 'app/api/v1/endpoints/__init__.py', - 'app/api/v1/endpoints/health.py', - 'app/api/v1/endpoints/auth.py', - 'app/api/v1/endpoints/files.py', - 'app/schemas/__init__.py', - 'app/schemas/user.py', - 'app/schemas/file.py' - ] - - all_exist = True - for file_path in required_files: - full_path = base_dir / file_path - if full_path.exists(): - print(f"✓ {file_path}") - else: - print(f"✗ {file_path}") - all_exist = False - - if all_exist: - print("\n🎉 所有文件创建成功!") - print("现在可以运行: python main.py") - else: - print("\n⚠️ 部分文件创建失败,请检查错误信息") - -def main(): - """主函数""" - print("=== 重新创建app目录结构 ===") - - # 创建目录结构 - create_app_directory() - - # 创建__init__.py文件 - create_init_files() - - # 创建核心文件 - create_core_files() - - # 创建API文件 - create_api_files() - - # 创建模式文件 - create_schema_files() - - # 验证结构 - verify_structure() - - print("\n=== 恢复完成 ===") - print("app目录结构和所有必要文件已重新创建") - print("下一步:") - print("1. 激活虚拟环境: source venv/bin/activate") - print("2. 安装依赖: pip install -r requirements.txt") - print("3. 启动服务: python main.py") - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/backend/server_no_loguru.py b/backend/server_no_loguru.py deleted file mode 100644 index 4ab5619..0000000 --- a/backend/server_no_loguru.py +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/env python3 -# 不依赖loguru的启动脚本 - -import os -import sys -import logging -from pathlib import Path - -# 添加当前目录到Python路径 -current_dir = Path(__file__).parent -sys.path.insert(0, str(current_dir)) - -# 配置标准日志 -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' -) -logger = logging.getLogger(__name__) - -logger.info("Starting Cloud Drive Application Server...") - -# 导入FastAPI相关 -try: - from fastapi import FastAPI - from fastapi.middleware.cors import CORSMiddleware - import uvicorn - logger.info("FastAPI dependencies available") -except ImportError as e: - logger.error(f"FastAPI import failed: {e}") - logger.error("Please install dependencies: pip install fastapi uvicorn") - sys.exit(1) - -# 尝试导入app模块 -try: - from app.core.config import settings - from app.api.v1.endpoints import health, auth, files - APP_AVAILABLE = True - logger.info("Full app module available") -except ImportError as e: - logger.warning(f"App module import failed: {e}") - logger.info("Using simplified mode") - APP_AVAILABLE = False - -def create_app(): - """创建FastAPI应用""" - if APP_AVAILABLE: - # 使用完整的应用 - app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # CORS中间件 - try: - app.add_middleware( - CORSMiddleware, - allow_origins=settings.ALLOWED_HOSTS, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - except Exception as e: - logger.warning(f"CORS configuration failed: {e}") - # 使用默认配置 - app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - # 包含路由 - try: - app.include_router(health.router, prefix="/api/v1", tags=["health"]) - app.include_router(auth.router, prefix="/api/v1/auth", tags=["authentication"]) - app.include_router(files.router, prefix="/api/v1/files", tags=["files"]) - except Exception as e: - logger.warning(f"Router inclusion failed: {e}") - - @app.get("/") - async def root(): - return { - "message": "云盘应用 API", - "version": "1.0.1", - "docs": "/docs", - "health": "/api/v1/health" - } - - # 添加缺失的端点 - @app.get("/health") - async def health_endpoint(): - import time - return { - "success": True, - "data": { - "status": "healthy", - "service": "cloud-drive-api", - "environment": "development", - "timestamp": int(time.time()) - }, - "message": "API服务运行正常" - } - - @app.get("/test") - async def test_endpoint(): - return { - "message": "测试端点正常工作", - "server": "port 8080", - "status": "ok" - } - - @app.get("/info") - async def info_endpoint(): - return { - "mode": "full", - "python_version": str(sys.version), - "status": "running", - "app_type": "FastAPI" - } - - return app - else: - # 创建简化版本的应用 - app = FastAPI( - title="云盘应用 API (简化版)", - description="云存储Web应用后端API - 简化版本", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # CORS中间件 - app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - @app.get("/") - async def root(): - return { - "message": "云盘应用 API (简化版)", - "version": "1.0.0", - "docs": "/docs", - "health": "/health", - "mode": "simplified" - } - - @app.get("/health") - async def health_check(): - return { - "status": "healthy", - "message": "服务运行正常", - "mode": "simplified" - } - - @app.get("/api/v1/health") - async def api_health(): - import time - return { - "status": "healthy", - "timestamp": time.time(), - "version": "1.0.0" - } - - @app.get("/test") - async def test_endpoint(): - return { - "message": "测试端点正常工作", - "server": "port 8080", - "status": "ok" - } - - @app.get("/health") - async def health_endpoint(): - import time - return { - "success": True, - "data": { - "status": "healthy", - "service": "cloud-drive-api", - "environment": "development", - "timestamp": int(time.time()) - }, - "message": "API服务运行正常" - } - - @app.get("/info") - async def info_endpoint(): - return { - "mode": "simplified", - "python_version": str(sys.version), - "status": "running", - "app_type": "FastAPI" - } - - return app - -def main(): - """主函数""" - logger.info("Initializing Cloud Drive Application...") - - # 创建必要目录 - os.makedirs("logs", exist_ok=True) - os.makedirs("uploads", exist_ok=True) - logger.info("Created necessary directories") - - # 创建FastAPI应用 - app = create_app() - logger.info("FastAPI application created") - - # 获取本机IP - try: - import socket - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("8.8.8.8", 80)) - local_ip = s.getsockname()[0] - s.close() - except: - local_ip = "127.0.0.1" - logger.warning("Could not determine local IP, using 127.0.0.1") - - # 显示启动信息 - logger.info("=" * 50) - logger.info(f"Local access:") - logger.info(f" Root path: http://localhost:8080") - logger.info(f" API docs: http://localhost:8080/docs") - logger.info(f" ReDoc: http://localhost:8080/redoc") - logger.info(f" Health check: http://localhost:8080/api/v1/health") - logger.info("") - logger.info(f"Network access:") - logger.info(f" Root path: http://{local_ip}:8080") - logger.info(f" API docs: http://{local_ip}:8080/docs") - logger.info("") - logger.info("Service information:") - logger.info(f" Python version: {sys.version}") - logger.info(f" Working directory: {os.getcwd()}") - logger.info(f" Mode: {'Full' if APP_AVAILABLE else 'Simplified'}") - logger.info("=" * 50) - logger.info("Press Ctrl+C to stop service") - - # 启动服务器 - try: - uvicorn.run( - app, - host="0.0.0.0", - port=8080, - reload=False, - access_log=True, - log_level="info" - ) - except KeyboardInterrupt: - logger.info("Server stopped by user") - except Exception as e: - logger.error(f"Startup failed: {e}") - logger.info("Possible solutions:") - logger.info("1. Check if port 8080 is occupied") - logger.info("2. Ensure dependencies are installed: pip install fastapi uvicorn") - logger.info("3. Check firewall settings") - return False - - return True - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/backend/simple-build.sh b/backend/simple-build.sh deleted file mode 100644 index 41096c7..0000000 --- a/backend/simple-build.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash - -# 简单的Docker镜像构建脚本 -# 当无法访问Docker Hub时使用 - -echo "=== 云盘应用 Docker 镜像构建工具 ===" - -# 检查可执行文件 -if [ ! -f "dist/cloud-drive-server.exe" ]; then - echo "错误: 未找到可执行文件" - echo "请先运行: python package-app.py" - exit 1 -fi - -# 创建临时目录 -TEMP_DIR="temp-docker" -rm -rf $TEMP_DIR -mkdir -p $TEMP_DIR - -echo "正在准备Docker镜像内容..." - -# 复制可执行文件 -cp dist/cloud-drive-server.exe $TEMP_DIR/ - -# 创建运行脚本 -cat > $TEMP_DIR/start.sh << 'EOF' -#!/bin/sh -# 设置时区 -export TZ=Asia/Shanghai -ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -# 创建必要目录 -mkdir -p /app/uploads /app/logs - -# 启动应用 -exec ./cloud-drive-server.exe -EOF - -chmod +x $TEMP_DIR/start.sh - -# 创建简化的Dockerfile -cat > $TEMP_DIR/Dockerfile << 'EOF' -# 使用scratch基础镜像(无依赖) -FROM scratch - -# 复制可执行文件和脚本 -COPY cloud-drive-server.exe / -COPY start.sh / - -# 设置执行权限 -CMD ["/start.sh"] -EOF - -echo "Docker镜像内容准备完成" -echo "临时目录: $TEMP_DIR" - -# 如果可以使用Docker -if command -v docker &> /dev/null; then - echo "正在构建Docker镜像..." - cd $TEMP_DIR - - # 尝试构建 - if docker build -t cloud-drive-backend:simple . 2>/dev/null; then - echo "OK Docker镜像构建成功" - echo "镜像名称: cloud-drive-backend:simple" - echo "" - echo "运行命令:" - echo " docker run -d -p 8002:8002 --name cloud-drive-backend cloud-drive-backend:simple" - else - echo "Docker镜像构建失败,可能是网络问题" - echo "请检查Docker网络配置或稍后重试" - fi - - cd .. -else - echo "未找到Docker命令" -fi - -echo "=== 构建完成 ===" \ No newline at end of file diff --git a/backend/simple_files_check.py b/backend/simple_files_check.py deleted file mode 100644 index f92be08..0000000 --- a/backend/simple_files_check.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python3 -""" -简化版文件存储检查脚本 -""" - -import mysql.connector -import os -import hashlib - -def check_files_storage(): - """检查文件存储情况""" - - print("=== 文件存储情况检查 ===") - - try: - # 连接数据库 - conn = mysql.connector.connect( - host="101.126.85.76", - user="mytest_db", - password="mytest_db", - database="mytest_db" - ) - cursor = conn.cursor() - - # 查询所有文件 - cursor.execute(""" - SELECT id, user_id, original_filename, filename, file_path, file_size, - file_hash, mime_type, created_at - FROM files - ORDER BY created_at DESC - """) - - db_files = cursor.fetchall() - print(f"数据库中的文件记录数: {len(db_files)}") - print() - - print("=== 数据库中的文件记录 ===") - for file in db_files: - (id, user_id, original_filename, filename, file_path, - file_size, file_hash, mime_type, created_at) = file - - print(f"ID: {id}") - print(f" 原始文件名: {original_filename}") - print(f" 存储文件名: {filename}") - print(f" 文件大小: {file_size} bytes") - print(f" MIME类型: {mime_type}") - print(f" 创建时间: {created_at}") - print("-" * 40) - - # 检查实际文件存在情况 - print("\n=== 文件存在性检查 ===") - existing_count = 0 - for file in db_files: - (id, user_id, original_filename, filename, file_path, - file_size, file_hash, mime_type, created_at) = file - - full_path = os.path.join("uploads", filename) - if os.path.exists(full_path): - existing_count += 1 - print(f"[存在] ID {id}: {original_filename}") - else: - print(f"[缺失] ID {id}: {original_filename}") - - print(f"\n实际存在的文件数: {existing_count}") - print(f"缺失的文件数: {len(db_files) - existing_count}") - - # 检查uploads目录详情 - print("\n=== uploads目录详情 ===") - uploads_dir = "uploads" - if os.path.exists(uploads_dir): - files = os.listdir(uploads_dir) - print(f"uploads目录中的文件数: {len(files)}") - - for file in files: - file_path = os.path.join(uploads_dir, file) - file_size = os.path.getsize(file_path) - print(f"文件: {file}, 大小: {file_size} bytes") - else: - print("uploads目录不存在") - - except Exception as e: - print(f"检查出错: {e}") - finally: - if 'conn' in locals() and conn.is_connected(): - cursor.close() - conn.close() - -def check_file_integrity(): - """检查文件完整性""" - - print("\n=== 文件完整性检查 ===") - - try: - conn = mysql.connector.connect( - host="101.126.85.76", - user="mytest_db", - password="mytest_db", - database="mytest_db" - ) - cursor = conn.cursor() - - cursor.execute("SELECT id, filename, file_hash, file_size FROM files") - db_files = cursor.fetchall() - - integrity_ok = True - - for (id, filename, expected_hash, expected_size) in db_files: - full_path = os.path.join("uploads", filename) - - if os.path.exists(full_path): - actual_size = os.path.getsize(full_path) - if actual_size != expected_size: - print(f"ID {id}: 文件大小不匹配 (期望: {expected_size}, 实际: {actual_size})") - integrity_ok = False - continue - - try: - with open(full_path, 'rb') as f: - content = f.read() - actual_hash = hashlib.sha256(content).hexdigest() - - if actual_hash != expected_hash: - print(f"ID {id}: 文件哈希不匹配") - print(f" 期望: {expected_hash}") - print(f" 实际: {actual_hash}") - integrity_ok = False - else: - print(f"ID {id}: 完整性检查通过") - except Exception as e: - print(f"ID {id}: 无法计算哈希 - {e}") - integrity_ok = False - else: - print(f"ID {id}: 文件不存在") - integrity_ok = False - - if integrity_ok: - print("所有文件完整性检查通过!") - else: - print("发现文件完整性问题!") - - except Exception as e: - print(f"完整性检查出错: {e}") - finally: - if 'conn' in locals() and conn.is_connected(): - cursor.close() - conn.close() - -if __name__ == "__main__": - check_files_storage() - check_file_integrity() - - print("\n=== 文件存储架构总结 ===") - print("1. 数据库(files表): 存储文件元数据") - print(" - 文件ID、用户ID、原始文件名") - print(" - 存储文件名(UUID格式)") - print(" - 文件大小、MIME类型") - print(" - SHA-256哈希值") - print(" - 创建时间等") - print() - print("2. 文件系统(uploads目录): 存储实际文件") - print(" - 文件使用UUID命名确保唯一性") - print(" - 文件内容与数据库记录一一对应") - print(" - 通过file_hash验证完整性") - print() - print("3. 回答您的问题:") - print(" 是的,数据库中存储的是文件元数据,") - print(" 实际文件内容存储在服务器的uploads目录中。") - print(" 两者通过file_hash保持关联和完整性验证。") \ No newline at end of file diff --git a/backend/simple_hash_demo.py b/backend/simple_hash_demo.py deleted file mode 100644 index 048f68f..0000000 --- a/backend/simple_hash_demo.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/env python3 -""" -简化版文件哈希演示脚本 -""" - -import hashlib -import requests -import os - -# API基础URL -BASE_URL = "http://localhost:8000/api/v1" -USER_ID = 8 - -def calculate_sha256_hash(file_content: bytes) -> str: - """计算文件的SHA-256哈希值""" - return hashlib.sha256(file_content).hexdigest() - -def upload_and_demo_hash(): - """上传文件并演示哈希功能""" - - # 创建测试文件内容 - original_content = "Hello World! 这是演示文件哈希的测试内容。" - - print("=== 文件哈希演示 ===") - print("原始文件内容:") - print(f"'{original_content}'") - print(f"文件大小: {len(original_content.encode('utf-8'))} bytes") - print() - - # 计算哈希值 - file_hash = calculate_sha256_hash(original_content.encode('utf-8')) - print("计算的SHA-256哈希值:") - print(file_hash) - print() - - # 上传文件 - try: - files = { - "file": ("hash_demo.txt", original_content.encode('utf-8'), "text/plain") - } - data = { - "user_id": USER_ID, - "description": "哈希演示文件", - "tags": "demo,hash", - "is_public": "false" - } - - response = requests.post( - f"{BASE_URL}/files/upload", - files=files, - data=data - ) - - if response.status_code == 201: - result = response.json() - if result.get("success"): - file_info = result["data"]["file"] - server_hash = file_info["file_hash"] - file_id = file_info["id"] - - print("文件上传成功!") - print(f"文件ID: {file_id}") - print(f"服务器哈希值: {server_hash}") - print() - - # 验证哈希值一致性 - if file_hash == server_hash: - print("哈希值验证通过! 客户端和服务器计算结果一致") - else: - print("哈希值验证失败!") - print(f"客户端: {file_hash}") - print(f"服务器: {server_hash}") - - return file_id, original_content, file_hash, file_info['filename'] - else: - print(f"上传失败: {response.text}") - return None, None, None, None - - except Exception as e: - print(f"上传出错: {e}") - return None, None, None, None - -def verify_download_integrity(file_id, original_content, original_hash, filename): - """验证下载文件的完整性""" - - print("\n=== 文件下载和完整性验证 ===") - - try: - # 下载文件 - data = { - "user_id": USER_ID, - "file_id": file_id - } - - response = requests.post( - f"{BASE_URL}/files/download", - json=data - ) - - if response.status_code == 200: - downloaded_content = response.content.decode('utf-8') - - print("下载的文件内容:") - print(f"'{downloaded_content}'") - print() - - # 验证内容完整性 - if downloaded_content == original_content: - print("内容完整性验证通过!") - else: - print("内容完整性验证失败!") - - # 计算下载文件的哈希值 - downloaded_hash = calculate_sha256_hash(downloaded_content.encode('utf-8')) - print("下载文件的哈希值:") - print(downloaded_hash) - print() - - # 验证哈希值 - if downloaded_hash == original_hash: - print("下载文件哈希验证通过! 文件完整性得到保证") - else: - print("下载文件哈希验证失败! 文件可能已损坏") - print(f"原始哈希: {original_hash}") - print(f"下载哈希: {downloaded_hash}") - - else: - print(f"下载失败: {response.text}") - - except Exception as e: - print(f"下载过程出错: {e}") - -def show_server_file_info(filename): - """显示服务器上文件的信息""" - - print("\n=== 服务器文件信息 ===") - - # 检查uploads目录 - upload_path = os.path.join("uploads", filename) - if os.path.exists(upload_path): - file_size = os.path.getsize(upload_path) - print(f"文件路径: {upload_path}") - print(f"文件大小: {file_size} bytes") - - # 计算文件哈希 - with open(upload_path, 'rb') as f: - content = f.read() - file_hash = calculate_sha256_hash(content) - print(f"文件SHA-256哈希: {file_hash}") - - # 显示文件内容 - with open(upload_path, 'r', encoding='utf-8') as f: - content = f.read() - print(f"文件内容: '{content}'") - else: - print(f"文件不存在: {upload_path}") - -def demonstrate_hash_properties(): - """演示哈希的重要特性""" - - print("\n=== 哈希特性演示 ===") - - # 特性1: 相同输入产生相同哈希 - text1 = "Hello World" - text2 = "Hello World" - hash1 = calculate_sha256_hash(text1.encode()) - hash2 = calculate_sha256_hash(text2.encode()) - - print("特性1: 相同输入产生相同哈希") - print(f"文本1: '{text1}' -> {hash1}") - print(f"文本2: '{text2}' -> {hash2}") - print(f"哈希值相同: {hash1 == hash2}") - print() - - # 特性2: 微小变化导致完全不同的哈希 - text3 = "Hello World" - text4 = "Hello World!" # 只多了一个感叹号 - hash3 = calculate_sha256_hash(text3.encode()) - hash4 = calculate_sha256_hash(text4.encode()) - - print("特性2: 微小变化导致完全不同的哈希") - print(f"文本3: '{text3}' -> {hash3}") - print(f"文本4: '{text4}' -> {hash4}") - print(f"哈希值不同: {hash3 != hash4}") - print() - - # 特性3: 不可逆性 - sample_hash = "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e" - print("特性3: 哈希是单向的,无法从哈希反推原始内容") - print(f"示例哈希: {sample_hash}") - print("无法从这个哈希值推断出原始文本内容") - print() - -def main(): - """主演示函数""" - - # 演示哈希特性 - demonstrate_hash_properties() - - # 上传并演示哈希功能 - file_id, original_content, original_hash, filename = upload_and_demo_hash() - - if file_id: - # 验证下载完整性 - verify_download_integrity(file_id, original_content, original_hash, filename) - - # 显示服务器文件信息 - show_server_file_info(filename) - - print("\n=== 总结 ===") - print("file_hash 的作用:") - print("1. 完整性验证 - 确保文件在传输存储过程中未损坏") - print("2. 文件去重 - 相同内容只存储一份,节省空间") - print("3. 安全检查 - 防止恶意文件和内容篡改") - print("4. 快速比较 - 通过哈希值快速判断文件是否相同") - print() - print("如何还原文件:") - print("1. 通过API下载: POST /api/v1/files/download") - print("2. 直接从服务器目录读取: backend/uploads/[filename]") - print("3. 验证文件完整性: 计算SHA-256哈希并与数据库中的file_hash比较") - - else: - print("演示失败,无法上传测试文件") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/backend/simple_http_server.py b/backend/simple_http_server.py deleted file mode 100644 index 75442ac..0000000 --- a/backend/simple_http_server.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python3 -# 简单的HTTP服务器用于端口测试 - -from http.server import HTTPServer, BaseHTTPRequestHandler -import json -import socket -import time - -class SimpleHandler(BaseHTTPRequestHandler): - def do_GET(self): - print(f"收到请求: {self.path}") - - # 设置响应头 - self.send_response(200) - self.send_header('Content-Type', 'application/json') - self.send_header('Access-Control-Allow-Origin', '*') - self.end_headers() - - # 根据路径返回不同响应 - if self.path == '/': - response = { - "message": "简单HTTP服务器运行正常", - "port": 8080, - "status": "ok" - } - elif self.path == '/health': - response = { - "status": "healthy", - "timestamp": time.time(), - "server": "simple-http-server" - } - elif self.path == '/api/v1/health': - response = { - "status": "healthy", - "timestamp": time.time(), - "version": "1.0.0", - "server": "simple-http-server" - } - elif self.path == '/test': - response = { - "test": "ok", - "message": "测试端点正常工作" - } - else: - response = { - "error": "Not Found", - "message": "路径不存在", - "path": self.path - } - - self.wfile.write(json.dumps(response, ensure_ascii=False).encode('utf-8')) - - def do_OPTIONS(self): - # 处理CORS预检请求 - self.send_response(200) - self.send_header('Access-Control-Allow-Origin', '*') - self.send_header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') - self.send_header('Access-Control-Allow-Headers', 'Content-Type') - self.end_headers() - -def check_port_available(port): - """检查端口是否可用""" - try: - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.bind(('0.0.0.0', port)) - return True - except OSError: - return False - -def main(): - port = 8080 - - print("🔍 检查端口可用性...") - if not check_port_available(port): - print(f"❌ 端口 {port} 被占用") - # 尝试其他端口 - for test_port in range(8001, 8010): - if check_port_available(test_port): - print(f"✅ 使用端口 {test_port}") - port = test_port - break - else: - print("❌ 无法找到可用端口") - return - - print(f"🚀 启动简单HTTP服务器在端口 {port}") - print("=" * 50) - print(f"📍 本地访问: http://localhost:{port}") - print(f"📋 测试端点:") - print(f" 根路径: http://localhost:{port}/") - print(f" 健康检查: http://localhost:{port}/health") - print(f" API健康: http://localhost:{port}/api/v1/health") - print(f" 测试端点: http://localhost:{port}/test") - print("=" * 50) - print("⏹️ 按 Ctrl+C 停止服务") - - try: - server = HTTPServer(('0.0.0.0', port), SimpleHandler) - print(f"✅ 服务器已启动在端口 {port}") - server.serve_forever() - except KeyboardInterrupt: - print("\n🛑 服务器已停止") - except Exception as e: - print(f"❌ 服务器错误: {e}") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/backend/simple_main.py b/backend/simple_main.py deleted file mode 100644 index 823fa0a..0000000 --- a/backend/simple_main.py +++ /dev/null @@ -1,79 +0,0 @@ -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware -import time - -app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" -) - -# CORS中间件 -app.add_middleware( - CORSMiddleware, - allow_origins=["http://localhost:3000", "http://127.0.0.1:3000"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -@app.get("/") -async def root(): - return {"message": "云盘应用 API", "version": "1.0.0"} - -@app.get("/api/v1/health") -async def health_check(): - """基础健康检查""" - return { - "success": True, - "data": { - "status": "healthy", - "service": "cloud-drive-api", - "environment": "development", - "timestamp": int(time.time()) - }, - "message": "API服务运行正常" - } - -@app.get("/api/v1/ready") -async def readiness_check(): - """就绪检查 - 简化版本,不检查数据库""" - checks = { - "api": { - "status": "healthy", - "message": "API服务正常" - }, - "database": { - "status": "unknown", - "message": "数据库连接未配置(简化模式)" - }, - "redis": { - "status": "unknown", - "message": "Redis连接未配置(简化模式)" - }, - "storage": { - "status": "healthy", - "message": "文件存储正常" - } - } - - return { - "success": True, - "data": { - "status": "ready", - "checks": checks, - "timestamp": int(time.time()) - }, - "message": "API服务已就绪(简化模式)" - } - -if __name__ == "__main__": - import uvicorn - uvicorn.run( - "simple_main:app", - host="0.0.0.0", - port=8000, - reload=True - ) \ No newline at end of file diff --git a/backend/simple_server_8080.py b/backend/simple_server_8080.py deleted file mode 100644 index 7ff0e37..0000000 --- a/backend/simple_server_8080.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python3 -# 简化版FastAPI服务器 - 端口8080 - -import sys -import os -from pathlib import Path - -# 添加当前目录到Python路径 -current_dir = Path(__file__).parent -sys.path.insert(0, str(current_dir)) - -try: - from fastapi import FastAPI - from fastapi.middleware.cors import CORSMiddleware - import uvicorn - FASTAPI_AVAILABLE = True -except ImportError: - print("❌ FastAPI未安装,正在安装基础依赖...") - import subprocess - subprocess.run([sys.executable, "-m", "pip", "install", "fastapi", "uvicorn", "requests"]) - from fastapi import FastAPI - from fastapi.middleware.cors import CORSMiddleware - import uvicorn - FASTAPI_AVAILABLE = True - -# 尝试导入app模块 -try: - from app.core.config import settings - from app.api.v1.endpoints import health, auth, files - APP_AVAILABLE = True - print("✅ 完整app模块可用") -except ImportError as e: - print(f"⚠️ App模块导入失败: {e}") - print("🔧 使用简化模式启动...") - APP_AVAILABLE = False - -def create_app(): - """创建FastAPI应用""" - if APP_AVAILABLE: - # 使用完整的应用 - app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # CORS中间件 - try: - app.add_middleware( - CORSMiddleware, - allow_origins=settings.ALLOWED_HOSTS, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - except: - # 如果settings有问题,使用默认配置 - app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - # 包含路由 - try: - app.include_router(health.router, prefix="/api/v1", tags=["health"]) - app.include_router(auth.router, prefix="/api/v1/auth", tags=["authentication"]) - app.include_router(files.router, prefix="/api/v1/files", tags=["files"]) - except Exception as e: - print(f"⚠️ 路由包含失败: {e}") - - @app.get("/") - async def root(): - return { - "message": "云盘应用 API", - "version": "1.0.1", - "docs": "/docs", - "health": "/api/v1/health", - "mode": "full" - } - - return app - else: - # 创建简化版本的应用 - app = FastAPI( - title="云盘应用 API (简化版)", - description="云存储Web应用后端API - 简化版本", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # CORS中间件 - app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - @app.get("/") - async def root(): - return { - "message": "云盘应用 API (简化版)", - "version": "1.0.0", - "docs": "/docs", - "health": "/health", - "mode": "simplified" - } - - @app.get("/health") - async def health_check(): - return { - "status": "healthy", - "message": "服务运行正常", - "mode": "simplified" - } - - @app.get("/api/v1/health") - async def api_health(): - import time - return { - "status": "healthy", - "timestamp": time.time(), - "version": "1.0.0" - } - - @app.get("/api/v1/test") - async def test_endpoint(): - return { - "message": "测试端点正常工作", - "server": "port 8080", - "status": "ok" - } - - return app - -def main(): - """主函数""" - print("🚀 启动云盘应用服务器...") - print("=" * 50) - - # 创建必要目录 - os.makedirs("logs", exist_ok=True) - os.makedirs("uploads", exist_ok=True) - - # 创建FastAPI应用 - app = create_app() - - # 获取本机IP - try: - import socket - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("8.8.8.8", 80)) - local_ip = s.getsockname()[0] - s.close() - except: - local_ip = "127.0.0.1" - - # 显示启动信息 - print(f"📍 本地访问:") - print(f" 根路径: http://localhost:8080") - print(f" API文档: http://localhost:8080/docs") - print(f" ReDoc: http://localhost:8080/redoc") - print(f" 健康检查: http://localhost:8080/api/v1/health") - print(f" 测试端点: http://localhost:8080/api/v1/test") - print("") - print(f"🌐 网络访问:") - print(f" 根路径: http://{local_ip}:8080") - print(f" API文档: http://{local_ip}:8080/docs") - print("") - print("🔧 服务信息:") - print(f" Python版本: {sys.version}") - print(f" 工作目录: {os.getcwd()}") - print(f" 启动模式: {'完整版' if APP_AVAILABLE else '简化版'}") - print("=" * 50) - print("⏹️ 按 Ctrl+C 停止服务") - print("") - - # 启动服务器 - try: - uvicorn.run( - app, - host="0.0.0.0", - port=8080, - reload=False, - access_log=True, - log_level="info" - ) - except KeyboardInterrupt: - print("\n🛑 服务已停止") - except Exception as e: - print(f"❌ 启动失败: {e}") - print("\n💡 可能的解决方案:") - print("1. 检查端口8080是否被占用") - print("2. 确保安装了必要的依赖: pip install fastapi uvicorn") - print("3. 检查防火墙设置") - return False - - return True - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/backend/simple_start.py b/backend/simple_start.py deleted file mode 100644 index 01ada15..0000000 --- a/backend/simple_start.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -# 最简单的启动方式 - -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware -import uvicorn - -app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" -) - -# CORS中间件 -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -@app.get("/") -async def root(): - return { - "message": "云盘应用 API", - "version": "1.0.0", - "docs": "/docs", - "health": "/health" - } - -@app.get("/health") -async def health(): - return { - "status": "healthy", - "message": "服务运行正常" - } - -if __name__ == "__main__": - print("🚀 启动云盘后端服务...") - print("📍 服务地址: http://localhost:8000") - print("📚 API文档: http://localhost:8000/docs") - print("❤️ 健康检查: http://localhost:8000/health") - print("⏹️ 按 Ctrl+C 停止服务") - print("=" * 50) - - uvicorn.run( - app, - host="0.0.0.0", - port=8000, - reload=False - ) \ No newline at end of file diff --git a/backend/simple_test.py b/backend/simple_test.py deleted file mode 100644 index 8138b63..0000000 --- a/backend/simple_test.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python3 -""" -简单的文件上传测试脚本 -""" - -import requests -import json - -# API基础URL -BASE_URL = "http://localhost:8000/api/v1" - -def test_auth(): - """测试认证""" - # 先注册 - register_data = { - "username": "testuser", - "email": "test@example.com", - "password": "TestPass123!", - "confirm_password": "TestPass123!" - } - - try: - print("尝试注册用户...") - reg_response = requests.post(f"{BASE_URL}/auth/register", json=register_data) - print(f"注册状态码: {reg_response.status_code}") - - if reg_response.status_code == 201: - reg_result = reg_response.json() - if reg_result.get("success"): - token = reg_result["data"]["tokens"]["access_token"] - print("注册成功,获得token") - return token - else: - print(f"注册失败: {reg_result}") - else: - print(f"注册请求失败,状态码: {reg_response.status_code}") - - # 如果注册失败,尝试登录 - print("尝试登录用户...") - login_data = { - "username": "testuser", - "password": "testpass123" - } - - response = requests.post(f"{BASE_URL}/auth/login", json=login_data) - print(f"登录状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - print(f"登录结果: {result.get('success', False)}") - if result.get("success"): - token = result["data"]["tokens"]["access_token"] - print("登录成功,获得token") - return token - else: - print(f"登录失败: {result}") - - return None - except Exception as e: - print(f"认证出错: {e}") - return None - -def test_file_upload(token): - """测试文件上传""" - headers = { - "Authorization": f"Bearer {token}" - } - - # 创建测试文件 - test_content = "Hello World! 测试文件内容" - - try: - files = { - "file": ("test.txt", test_content.encode("utf-8"), "text/plain") - } - data = { - "description": "测试文件", - "tags": "test,upload", - "is_public": "false" - } - - response = requests.post( - f"{BASE_URL}/files/upload", - headers=headers, - files=files, - data=data - ) - - print(f"上传状态码: {response.status_code}") - print(f"上传响应: {response.text}") - - if response.status_code == 201: - result = response.json() - if result.get("success"): - file_info = result["data"]["file"] - print(f"上传成功! 文件ID: {file_info['id']}") - return file_info['id'] - - return None - except Exception as e: - print(f"上传出错: {e}") - return None - -def test_file_list(token): - """测试获取文件列表""" - headers = { - "Authorization": f"Bearer {token}" - } - - try: - response = requests.get( - f"{BASE_URL}/files/list", - headers=headers - ) - - print(f"列表状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - files = result["data"]["files"] - print(f"文件数量: {len(files)}") - for f in files: - print(f" - {f['original_filename']} ({f['file_size']} bytes)") - - except Exception as e: - print(f"获取列表出错: {e}") - -def test_storage_info(token): - """测试存储信息""" - headers = { - "Authorization": f"Bearer {token}" - } - - try: - response = requests.get( - f"{BASE_URL}/files/storage/info", - headers=headers - ) - - print(f"存储信息状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - info = result["data"] - print(f"存储配额: {info['total_quota']} bytes") - print(f"已使用: {info['used_space']} bytes") - print(f"文件数量: {info['file_count']}") - - except Exception as e: - print(f"获取存储信息出错: {e}") - -if __name__ == "__main__": - print("开始测试文件存储功能...") - - # 1. 认证 - token = test_auth() - if not token: - print("认证失败,退出测试") - exit(1) - - # 2. 上传文件 - file_id = test_file_upload(token) - - # 3. 获取文件列表 - test_file_list(token) - - # 4. 获取存储信息 - test_storage_info(token) - - print("测试完成!") \ No newline at end of file diff --git a/backend/simple_upload_test.py b/backend/simple_upload_test.py deleted file mode 100644 index 7e062a5..0000000 --- a/backend/simple_upload_test.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -简单上传下载测试 -""" - -import requests -import sys -import io - -# 设置stdout编码为utf-8 -sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") - -BASE_URL = "http://localhost:8000/api/v1" - -def simple_test(): - print("=== 简单上传下载测试 ===") - - # 使用存在的用户ID (用户ID=3存在) - user_id = 3 - print(f"使用用户ID: {user_id}") - - # 直接测试下载现有文件 (文件ID=24, test.txt) - file_id = 24 - print(f"\n直接下载现有文件 ID: {file_id} (test.txt)...") - - download_data = { - "file_id": file_id, - "user_id": user_id - } - - try: - download_resp = requests.post(f"{BASE_URL}/files/download", json=download_data) - print(f"下载状态码: {download_resp.status_code}") - print(f"下载响应头: {dict(download_resp.headers)}") - - if download_resp.status_code == 200: - downloaded_content = download_resp.text - print(f"[OK] 下载成功") - print(f"下载内容: {downloaded_content}") - print(f"内容长度: {len(downloaded_content)}") - - # 读取原始文件内容进行对比 - try: - with open(f"uploads/608408b0-02c7-449e-ba58-be43c4360333.txt", 'r', encoding='utf-8') as f: - original_content = f.read() - print(f"原始文件长度: {len(original_content)}") - - if original_content == downloaded_content: - print("[OK] 内容一致!上传下载功能正常") - else: - print("[ERROR] 内容不一致") - print(f"原始: {repr(original_content[:100])}") - print(f"下载: {repr(downloaded_content[:100])}") - except Exception as e: - print(f"无法读取原始文件进行对比: {e}") - - else: - print(f"[ERROR] 下载失败: {download_resp.text}") - except Exception as e: - print(f"[ERROR] 下载异常: {e}") - import traceback - traceback.print_exc() - - # 现在测试上传新文件 - print(f"\n=== 测试上传新文件 ===") - test_content = f"这是全新的测试文件内容\nBrand new test file content\n唯一时间戳: {hash('unique_content_' + str(__import__('time').time()))}" - - files = {"file": (f"unique_test_{hash(test_content) % 10000}.txt", test_content, "text/plain")} - data = { - "user_id": str(user_id), - "description": "新测试文件", - "tags": "test,new", - "is_public": "false" - } - - try: - upload_resp = requests.post(f"{BASE_URL}/files/upload", files=files, data=data) - print(f"上传状态码: {upload_resp.status_code}") - - if upload_resp.status_code == 201: - new_file_id = upload_resp.json()["data"]["file"]["id"] - print(f"[OK] 新文件上传成功,文件ID: {new_file_id}") - - # 立即下载新文件 - print(f"\n下载新上传的文件 ID: {new_file_id}...") - download_data = { - "file_id": new_file_id, - "user_id": user_id - } - - download_resp = requests.post(f"{BASE_URL}/files/download", json=download_data) - if download_resp.status_code == 200: - new_downloaded_content = download_resp.text - print(f"[OK] 新文件下载成功") - print(f"下载内容: {new_downloaded_content}") - - if test_content == new_downloaded_content: - print("[OK] 新文件内容一致!") - else: - print("[ERROR] 新文件内容不一致") - else: - print(f"[ERROR] 新文件下载失败: {download_resp.text}") - else: - print(f"[ERROR] 新文件上传失败: {upload_resp.text}") - except Exception as e: - print(f"[ERROR] 新文件测试异常: {e}") - import traceback - traceback.print_exc() - -if __name__ == "__main__": - simple_test() diff --git a/backend/start_8080.py b/backend/start_8080.py deleted file mode 100644 index f3c0e16..0000000 --- a/backend/start_8080.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -云盘应用启动脚本 - 端口8080版本 -包含完整的API测试功能 -""" - -import os -import sys -from pathlib import Path - -# 添加当前目录到Python路径 -current_dir = Path(__file__).parent -sys.path.insert(0, str(current_dir)) - -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware -import uvicorn -import subprocess -import time -import requests -from typing import Dict, List - -# 导入应用模块 -try: - from app.core.config import settings - from app.api.v1.endpoints import health, auth, files - APP_AVAILABLE = True -except ImportError as e: - print(f"⚠️ App模块导入失败: {e}") - print("🔧 使用简化模式启动...") - APP_AVAILABLE = False - -def create_fastapi_app(): - """创建FastAPI应用""" - if APP_AVAILABLE: - # 使用完整的应用 - app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # CORS中间件 - app.add_middleware( - CORSMiddleware, - allow_origins=settings.ALLOWED_HOSTS, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - # 包含路由 - app.include_router(health.router, prefix="/api/v1", tags=["health"]) - app.include_router(auth.router, prefix="/api/v1/auth", tags=["authentication"]) - app.include_router(files.router, prefix="/api/v1/files", tags=["files"]) - - @app.get("/") - async def root(): - return { - "message": "云盘应用 API", - "version": "1.0.1", - "docs": "/docs", - "health": "/api/v1/health" - } - - return app - else: - # 创建简化版本的应用 - app = FastAPI( - title="云盘应用 API (简化版)", - description="云存储Web应用后端API - 简化版本", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # CORS中间件 - app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - @app.get("/") - async def root(): - return { - "message": "云盘应用 API (简化版)", - "version": "1.0.0", - "docs": "/docs", - "health": "/health" - } - - @app.get("/health") - async def health_check(): - return { - "status": "healthy", - "message": "服务运行正常", - "mode": "simplified" - } - - @app.get("/api/v1/health") - async def api_health(): - return { - "status": "healthy", - "timestamp": time.time(), - "version": "1.0.0" - } - - return app - -def test_api_endpoints(base_url: str = "http://localhost:8080") -> Dict[str, any]: - """测试API端点""" - print("\n🧪 开始测试API端点...") - print("=" * 50) - - results = {} - - # 测试端点列表 - endpoints = [ - ("/", "根路径"), - ("/health", "健康检查"), - ("/api/v1/health", "API健康检查"), - ("/docs", "API文档"), - ("/redoc", "ReDoc文档"), - ("/openapi.json", "OpenAPI规范") - ] - - for endpoint, description in endpoints: - try: - print(f"📍 测试 {description}: {endpoint}") - - if endpoint in ["/docs", "/redoc"]: - # 对于文档端点,只检查HTTP状态 - response = requests.get(f"{base_url}{endpoint}", timeout=5) - if response.status_code == 200: - print(f" ✅ {description} - 状态码: {response.status_code}") - results[endpoint] = {"status": "success", "code": response.status_code} - else: - print(f" ❌ {description} - 状态码: {response.status_code}") - results[endpoint] = {"status": "failed", "code": response.status_code} - else: - # 对于API端点,检查响应内容 - response = requests.get(f"{base_url}{endpoint}", timeout=5) - if response.status_code == 200: - data = response.json() - print(f" ✅ {description} - 响应: {data}") - results[endpoint] = {"status": "success", "data": data} - else: - print(f" ❌ {description} - 状态码: {response.status_code}") - results[endpoint] = {"status": "failed", "code": response.status_code} - - except requests.exceptions.ConnectionError: - print(f" ❌ {description} - 连接失败") - results[endpoint] = {"status": "connection_failed"} - except requests.exceptions.Timeout: - print(f" ❌ {description} - 请求超时") - results[endpoint] = {"status": "timeout"} - except Exception as e: - print(f" ❌ {description} - 错误: {e}") - results[endpoint] = {"status": "error", "error": str(e)} - - return results - -def start_server(): - """启动服务器""" - print("🚀 启动云盘应用服务...") - print("=" * 50) - - # 创建必要目录 - os.makedirs("logs", exist_ok=True) - os.makedirs("uploads", exist_ok=True) - - # 创建FastAPI应用 - app = create_fastapi_app() - - # 获取本机IP - import socket - try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("8.8.8.8", 80)) - local_ip = s.getsockname()[0] - s.close() - except: - local_ip = "127.0.0.1" - - # 显示启动信息 - print(f"📍 本地访问:") - print(f" 根路径: http://localhost:8080") - print(f" API文档: http://localhost:8080/docs") - print(f" ReDoc: http://localhost:8080/redoc") - print(f" 健康检查: http://localhost:8080/api/v1/health") - print("") - print(f"🌐 网络访问:") - print(f" 根路径: http://{local_ip}:8080") - print(f" API文档: http://{local_ip}:8080/docs") - print(f" ReDoc: http://{local_ip}:8080/redoc") - print("") - print(f"🔧 API测试:") - print(f" 自动测试将在服务启动后执行") - print("=" * 50) - print("⏹️ 按 Ctrl+C 停止服务") - print("") - - # 启动服务器 - try: - uvicorn.run( - app, - host="0.0.0.0", - port=8080, - reload=False, - access_log=True, - log_level="info" - ) - except KeyboardInterrupt: - print("\n🛑 服务已停止") - except Exception as e: - print(f"❌ 启动失败: {e}") - return False - - return True - -def run_with_auto_test(): - """启动服务器并自动测试""" - print("🤖 自动模式:启动服务器并进行API测试") - - # 启动服务器(在后台) - import subprocess - import signal - import threading - - # 启动服务器进程 - server_process = subprocess.Popen([ - sys.executable, __file__ - ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - # 等待服务器启动 - print("⏳ 等待服务器启动...") - time.sleep(5) - - try: - # 测试API端点 - results = test_api_endpoints() - - # 显示测试结果 - print("\n📊 测试结果汇总:") - print("=" * 50) - - success_count = sum(1 for r in results.values() if r.get("status") == "success") - total_count = len(results) - - print(f"成功: {success_count}/{total_count}") - - for endpoint, result in results.items(): - status = result.get("status", "unknown") - if status == "success": - print(f" ✅ {endpoint}") - else: - print(f" ❌ {endpoint} - {status}") - - if success_count == total_count: - print("\n🎉 所有API端点测试通过!") - else: - print(f"\n⚠️ {total_count - success_count} 个端点测试失败") - - finally: - # 停止服务器 - print("\n🛑 停止服务器...") - server_process.terminate() - server_process.wait() - -if __name__ == "__main__": - import argparse - - parser = argparse.ArgumentParser(description="云盘应用启动器 - 端口8080") - parser.add_argument("--test", action="store_true", help="启动后自动测试API端点") - parser.add_argument("--auto", action="store_true", help="自动模式:启动并测试") - args = parser.parse_args() - - if args.auto: - run_with_auto_test() - elif args.test: - # 先启动,再测试 - print("🚀 启动服务器...") - app = create_fastapi_app() - - # 在单独线程中启动服务器 - import threading - - def run_server(): - uvicorn.run(app, host="0.0.0.0", port=8080, reload=False, log_level="warning") - - server_thread = threading.Thread(target=run_server, daemon=True) - server_thread.start() - - # 等待服务器启动 - time.sleep(3) - - # 测试API - test_api_endpoints() - - print("\n服务器继续运行,按 Ctrl+C 停止...") - try: - while True: - time.sleep(1) - except KeyboardInterrupt: - print("\n🛑 服务已停止") - else: - # 正常启动 - start_server() \ No newline at end of file diff --git a/backend/start_and_test_8080.sh b/backend/start_and_test_8080.sh deleted file mode 100644 index 67028d8..0000000 --- a/backend/start_and_test_8080.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# 启动服务并测试API的脚本 - -echo "🚀 云盘应用启动和测试脚本" -echo "==================================" - -# 检查Python环境 -if ! command -v python3 &> /dev/null; then - echo "❌ Python3 未安装" - exit 1 -fi - -echo "✅ Python3 已安装" - -# 检查端口8080是否被占用 -if lsof -Pi :8080 -sTCP:LISTEN -t >/dev/null ; then - echo "❌ 端口8080已被占用" - echo "🔧 尝试停止占用端口的进程..." - lsof -ti:8080 | xargs kill -9 2>/dev/null || echo "无法停止进程" - sleep 2 -fi - -# 启动服务器(后台) -echo "🚀 启动服务器在端口8080..." -python3 start_8080.py & -SERVER_PID=$! - -# 等待服务器启动 -echo "⏳ 等待服务器启动..." -sleep 5 - -# 测试服务器是否启动成功 -if curl -s http://localhost:8080/health > /dev/null; then - echo "✅ 服务器启动成功" -else - echo "❌ 服务器启动失败" - kill $SERVER_PID 2>/dev/null - exit 1 -fi - -# 运行API测试 -echo "" -echo "🧪 开始API测试..." -echo "==================================" -python3 test_api_8080.py - -# 停止服务器 -echo "" -echo "🛑 停止服务器..." -kill $SERVER_PID 2>/dev/null -wait $SERVER_PID 2>/dev/null - -echo "" -echo "✅ 测试完成!" \ No newline at end of file diff --git a/backend/start_simple.py b/backend/start_simple.py deleted file mode 100644 index e0841c8..0000000 --- a/backend/start_simple.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python3 -# 简化版启动脚本,解决模块导入问题 - -import os -import sys -from pathlib import Path - -# 添加当前目录到Python路径 -current_dir = Path(__file__).parent -sys.path.insert(0, str(current_dir)) - -print(f"当前目录: {current_dir}") -print(f"Python路径: {sys.path[:3]}...") - -# 检查必要目录 -required_dirs = ['app', 'app/core', 'app/api/v1/endpoints'] -for dir_path in required_dirs: - full_path = current_dir / dir_path - if not full_path.exists(): - print(f"创建目录: {dir_path}") - full_path.mkdir(parents=True, exist_ok=True) - - # 创建__init__.py - init_file = full_path / '__init__.py' - if not init_file.exists(): - init_file.write_text(f'"""{dir_path} 模块包"""\n') - -try: - # 测试导入 - print("测试导入模块...") - from app.core.config import settings - print("✓ app.core.config 导入成功") - - from app.api.v1.endpoints import health, auth, files - print("✓ app.api.v1.endpoints 导入成功") - - # 启动FastAPI应用 - from fastapi import FastAPI - from fastapi.middleware.cors import CORSMiddleware - import uvicorn - - app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # CORS中间件 - app.add_middleware( - CORSMiddleware, - allow_origins=["*"], # 临时允许所有来源 - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - # 包含路由 - app.include_router(health.router, prefix="/api/v1", tags=["health"]) - app.include_router(auth.router, prefix="/api/v1/auth", tags=["authentication"]) - app.include_router(files.router, prefix="/api/v1/files", tags=["files"]) - - @app.get("/") - async def root(): - return {"message": "云盘应用 API", "version": "1.0.1"} - - print("✓ FastAPI应用创建成功") - - # 启动服务 - print("启动服务...") - print("访问地址: http://localhost:8000") - print("API文档: http://localhost:8000/docs") - - uvicorn.run( - app, - host="0.0.0.0", - port=8000, - reload=False # 关闭热重载避免问题 - ) - -except ImportError as e: - print(f"导入错误: {e}") - print("\n可能的解决方案:") - print("1. 确保在正确的目录运行(包含main.py的目录)") - print("2. 安装依赖: pip install fastapi uvicorn sqlalchemy pymysql redis python-jose passlib python-multipart pydantic pydantic-settings httpx python-dotenv loguru") - print("3. 检查app目录结构是否完整") - sys.exit(1) - -except Exception as e: - print(f"启动错误: {e}") - sys.exit(1) \ No newline at end of file diff --git a/backend/test-main.py b/backend/test-main.py deleted file mode 100644 index 41f8d0e..0000000 --- a/backend/test-main.py +++ /dev/null @@ -1,76 +0,0 @@ -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware -from app.core.config import settings -from app.api.v1.endpoints import health, auth, files -import uvicorn -from datetime import datetime -import sys -import os - -# 简单的日志打印函数 -def log_info(message): - """打印INFO级别日志""" - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - print(f"[{timestamp}] INFO: {message}") - -def log_error(message): - """打印ERROR级别日志""" - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - print(f"[{timestamp}] ERROR: {message}") - -def log_debug(message): - """打印DEBUG级别日志""" - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - print(f"[{timestamp}] DEBUG: {message}") - -# 确保logs目录存在 -os.makedirs("logs", exist_ok=True) - -log_info("=== Test Server Starting ===") -log_info(f"Python version: {sys.version}") -log_info(f"Working directory: {os.getcwd()}") -log_info("Simple print logger configured") - -app = FastAPI( - title="云盘应用 API (测试环境)", - description="现代化的云存储Web应用后端API - 测试环境", - version="1.0.0-test", - docs_url="/docs", - redoc_url="/redoc" -) - -# CORS中间件 -app.add_middleware( - CORSMiddleware, - allow_origins=settings.ALLOWED_HOSTS, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -# 包含路由 -app.include_router(health.router, prefix="/api/v1", tags=["health"]) -app.include_router(auth.router, prefix="/api/v1/auth", tags=["authentication"]) -app.include_router(files.router, prefix="/api/v1/files", tags=["files"]) - -@app.get("/") -async def root(): - return {"message": "云盘应用 API (测试环境)", "version": "1.0.1-test", "port": 8010} - -@app.get("/test") -async def test(): - return {"status": "ok", "message": "测试服务器运行正常", "port": 8010} - -if __name__ == "__main__": - # 设置测试端口 - test_port = 8010 - - # 临时设置环境变量覆盖配置 - os.environ["PORT"] = str(test_port) - - uvicorn.run( - "test-main:app", - host="0.0.0.0", - port=test_port, - reload=False # 测试环境不使用热重载 - ) \ No newline at end of file diff --git a/backend/test_api_8080.py b/backend/test_api_8080.py deleted file mode 100644 index a4c667c..0000000 --- a/backend/test_api_8080.py +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -API测试脚本 - 测试端口8080上的所有端点 -""" - -import requests -import json -import time -from typing import Dict, List - -class CloudDriveAPITester: - def __init__(self, base_url: str = "http://localhost:8080"): - self.base_url = base_url - self.session = requests.Session() - self.session.headers.update({ - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }) - - def test_endpoint(self, method: str, endpoint: str, data: Dict = None, description: str = "") -> Dict: - """测试单个端点""" - url = f"{self.base_url}{endpoint}" - - try: - print(f"📍 {description or f'{method.upper()} {endpoint}'}") - - if method.upper() == 'GET': - response = self.session.get(url, timeout=10) - elif method.upper() == 'POST': - response = self.session.post(url, json=data, timeout=10) - elif method.upper() == 'PUT': - response = self.session.put(url, json=data, timeout=10) - elif method.upper() == 'DELETE': - response = self.session.delete(url, timeout=10) - else: - return {"status": "error", "message": f"不支持的HTTP方法: {method}"} - - if response.status_code == 200: - try: - data = response.json() - print(f" ✅ 成功 (200): {json.dumps(data, ensure_ascii=False, indent=2)[:200]}...") - return { - "status": "success", - "code": response.status_code, - "data": data - } - except json.JSONDecodeError: - print(f" ✅ 成功 (200): {response.text[:200]}...") - return { - "status": "success", - "code": response.status_code, - "text": response.text - } - else: - print(f" ❌ 失败 ({response.status_code}): {response.text[:200]}...") - return { - "status": "failed", - "code": response.status_code, - "error": response.text - } - - except requests.exceptions.ConnectionError: - print(f" ❌ 连接失败 - 无法连接到 {url}") - return {"status": "connection_failed", "error": "Connection failed"} - except requests.exceptions.Timeout: - print(f" ❌ 请求超时") - return {"status": "timeout", "error": "Request timeout"} - except Exception as e: - print(f" ❌ 未知错误: {e}") - return {"status": "error", "error": str(e)} - - def test_basic_endpoints(self) -> Dict: - """测试基础端点""" - print("🔍 测试基础端点") - print("=" * 50) - - results = {} - - # 测试根路径 - results["root"] = self.test_endpoint("GET", "/", description="根路径") - - # 测试健康检查端点 - results["health"] = self.test_endpoint("GET", "/health", description="健康检查") - results["api_health"] = self.test_endpoint("GET", "/api/v1/health", description="API健康检查") - - # 测试文档端点 - results["docs"] = self.test_endpoint("GET", "/docs", description="API文档") - results["redoc"] = self.test_endpoint("GET", "/redoc", description="ReDoc文档") - results["openapi"] = self.test_endpoint("GET", "/openapi.json", description="OpenAPI规范") - - return results - - def test_auth_endpoints(self) -> Dict: - """测试认证端点""" - print("\n🔐 测试认证端点") - print("=" * 50) - - results = {} - - # 测试注册端点 - test_user = { - "username": "testuser8080", - "email": "test8080@example.com", - "password": "Test123!@#", - "confirm_password": "Test123!@#" - } - results["register"] = self.test_endpoint("POST", "/api/v1/auth/register", - data=test_user, description="用户注册") - - # 测试登录端点 - login_data = { - "username": "testuser8080", - "password": "Test123!@#" - } - results["login"] = self.test_endpoint("POST", "/api/v1/auth/token", - data=login_data, description="用户登录") - - return results - - def test_file_endpoints(self) -> Dict: - """测试文件端点""" - print("\n📁 测试文件端点") - print("=" * 50) - - results = {} - - # 测试文件列表 - results["list_files"] = self.test_endpoint("GET", "/api/v1/files", - description="获取文件列表") - - # 测试文件上传(模拟) - results["upload_info"] = self.test_endpoint("GET", "/api/v1/files", - description="文件上传信息") - - return results - - def run_all_tests(self) -> Dict: - """运行所有测试""" - print("🧪 开始API测试 - 端口8080") - print("=" * 60) - print(f"测试目标: {self.base_url}") - print("=" * 60) - - all_results = {} - - # 测试基础端点 - basic_results = self.test_basic_endpoints() - all_results.update(basic_results) - - # 测试认证端点 - auth_results = self.test_auth_endpoints() - all_results.update(auth_results) - - # 测试文件端点 - file_results = self.test_file_endpoints() - all_results.update(file_results) - - # 生成测试报告 - self.generate_report(all_results) - - return all_results - - def generate_report(self, results: Dict): - """生成测试报告""" - print("\n📊 测试报告") - print("=" * 60) - - total_tests = len(results) - success_tests = sum(1 for r in results.values() if r.get("status") == "success") - failed_tests = total_tests - success_tests - - print(f"总测试数: {total_tests}") - print(f"成功: {success_tests}") - print(f"失败: {failed_tests}") - print(f"成功率: {(success_tests/total_tests*100):.1f}%") - - if failed_tests == 0: - print("\n🎉 所有测试通过!API服务运行正常") - else: - print(f"\n⚠️ 有 {failed_tests} 个测试失败,请检查服务状态") - - print("\n📋 详细结果:") - for endpoint, result in results.items(): - status = result.get("status", "unknown") - if status == "success": - print(f" ✅ {endpoint}") - elif status == "connection_failed": - print(f" 🔌 {endpoint} - 连接失败") - elif status == "timeout": - print(f" ⏰ {endpoint} - 超时") - else: - print(f" ❌ {endpoint} - {status}") - -def main(): - """主函数""" - import argparse - - parser = argparse.ArgumentParser(description="云盘API测试工具") - parser.add_argument("--url", default="http://localhost:8080", - help="API基础URL (默认: http://localhost:8080)") - parser.add_argument("--wait", type=int, default=0, - help="启动前等待时间(秒)") - parser.add_argument("--basic", action="store_true", help="只测试基础端点") - parser.add_argument("--auth", action="store_true", help="只测试认证端点") - parser.add_argument("--files", action="store_true", help="只测试文件端点") - - args = parser.parse_args() - - if args.wait > 0: - print(f"⏳ 等待 {args.wait} 秒后开始测试...") - time.sleep(args.wait) - - tester = CloudDriveAPITester(args.url) - - try: - if args.basic: - tester.test_basic_endpoints() - elif args.auth: - tester.test_auth_endpoints() - elif args.files: - tester.test_file_endpoints() - else: - tester.run_all_tests() - except KeyboardInterrupt: - print("\n🛑 测试已中断") - except Exception as e: - print(f"\n❌ 测试过程中出现错误: {e}") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/backend/test_api_exception.py b/backend/test_api_exception.py deleted file mode 100644 index 24762f9..0000000 --- a/backend/test_api_exception.py +++ /dev/null @@ -1,50 +0,0 @@ -import sys -import traceback -from fastapi import FastAPI -from fastapi.testclient import TestClient -from app.core.database import get_db -from app.services.user_service import UserService -from app.schemas.auth import UserRegister - -def test_api_exception(): - """测试API异常处理""" - try: - print("=== 测试API异常处理 ===") - - # 导入应用 - import sys - import os - sys.path.append(os.path.dirname(os.path.abspath(__file__))) - from main import app - - # 创建测试客户端 - client = TestClient(app) - - # 测试重复邮箱注册 - print("1. 测试重复邮箱注册...") - response = client.post("/api/v1/auth/register", json={ - "username": "test_api", - "email": "user@example.com", # 重复邮箱 - "password": "TestPass123!", - "confirm_password": "TestPass123!" - }) - - print(f" HTTP状态码: {response.status_code}") - print(f" 响应内容: {response.json()}") - - if response.status_code == 400: - print(" ✓ 正确返回400错误") - detail = response.json().get("detail", {}) - if detail.get("code") == "EMAIL_EXISTS": - print(" ✓ 正确返回EMAIL_EXISTS错误码") - else: - print(f" ✗ 错误码不正确: {detail.get('code')}") - else: - print(f" ✗ 状态码不正确,期望400,实际{response.status_code}") - - except Exception as e: - print(f"测试过程出错: {e}") - traceback.print_exc() - -if __name__ == "__main__": - test_api_exception() \ No newline at end of file diff --git a/backend/test_apis.py b/backend/test_apis.py deleted file mode 100644 index da26ec5..0000000 --- a/backend/test_apis.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 -import requests -import json -import time - -def test_api(): - base_url = "http://localhost:8080" - - print("Testing API endpoints...") - print("=" * 40) - - # Test endpoints - endpoints = [ - ("/", "Root endpoint"), - ("/health", "Health check"), - ("/api/v1/health", "API health"), - ("/test", "Test endpoint"), - ("/info", "Info endpoint") - ] - - results = {} - - for endpoint, description in endpoints: - try: - print(f"Testing {description}: {endpoint}") - response = requests.get(f"{base_url}{endpoint}", timeout=5) - - if response.status_code == 200: - data = response.json() - print(f" SUCCESS: {data}") - results[endpoint] = {"status": "success", "data": data} - else: - print(f" FAILED: Status code {response.status_code}") - results[endpoint] = {"status": "failed", "code": response.status_code} - - except requests.exceptions.ConnectionError: - print(f" FAILED: Connection error") - results[endpoint] = {"status": "connection_error"} - except requests.exceptions.Timeout: - print(f" FAILED: Timeout") - results[endpoint] = {"status": "timeout"} - except Exception as e: - print(f" FAILED: {e}") - results[endpoint] = {"status": "error", "error": str(e)} - - # Summary - print("\n" + "=" * 40) - print("Test Summary:") - - success_count = sum(1 for r in results.values() if r.get("status") == "success") - total_count = len(results) - - print(f"Total tests: {total_count}") - print(f"Successful: {success_count}") - print(f"Failed: {total_count - success_count}") - print(f"Success rate: {(success_count/total_count*100):.1f}%") - - if success_count == total_count: - print("\n🎉 All API tests passed!") - print("✅ Server is running correctly on port 8080") - print("✅ You can access:") - print(" - http://localhost:8080/docs (Swagger UI)") - print(" - http://localhost:8080/redoc (ReDoc)") - else: - print(f"\n⚠️ {total_count - success_count} tests failed") - - return results - -if __name__ == "__main__": - # Wait a bit for server to fully start - time.sleep(2) - test_api() \ No newline at end of file diff --git a/backend/test_basic_server.py b/backend/test_basic_server.py deleted file mode 100644 index 598cef6..0000000 --- a/backend/test_basic_server.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python3 -# 最基础的FastAPI测试服务器 - -import sys -import os - -print("🔍 检查Python环境...") -print(f"Python版本: {sys.version}") -print(f"当前目录: {os.getcwd()}") - -# 测试导入 -try: - import fastapi - print(f"✅ FastAPI可用: {fastapi.__version__}") -except ImportError as e: - print(f"❌ FastAPI不可用: {e}") - print("正在安装FastAPI...") - import subprocess - subprocess.run([sys.executable, "-m", "pip", "install", "fastapi", "uvicorn"]) - import fastapi - print(f"✅ FastAPI安装成功: {fastapi.__version__}") - -try: - import uvicorn - print(f"✅ Uvicorn可用: {uvicorn.__version__}") -except ImportError as e: - print(f"❌ Uvicorn不可用: {e}") - print("正在安装Uvicorn...") - import subprocess - subprocess.run([sys.executable, "-m", "pip", "install", "uvicorn"]) - import uvicorn - print(f"✅ Uvicorn安装成功: {uvicorn.__version__}") - -# 创建最简单的FastAPI应用 -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware - -app = FastAPI( - title="云盘应用测试", - description="测试服务器", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" -) - -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -@app.get("/") -async def root(): - return {"message": "服务器运行正常", "port": 8080, "status": "ok"} - -@app.get("/test") -async def test(): - return {"test": "ok", "server": "working"} - -@app.get("/api/v1/health") -async def health(): - import time - return {"status": "healthy", "timestamp": time.time(), "server": "port 8080"} - -if __name__ == "__main__": - print("🚀 启动测试服务器...") - print("=" * 40) - print("📍 本地访问: http://localhost:8080") - print("📚 API文档: http://localhost:8080/docs") - print("=" * 40) - print("按 Ctrl+C 停止服务") - - try: - uvicorn.run(app, host="0.0.0.0", port=8080, log_level="info") - except Exception as e: - print(f"❌ 启动失败: {e}") \ No newline at end of file diff --git a/backend/test_blacklist.py b/backend/test_blacklist.py deleted file mode 100644 index 3439f54..0000000 --- a/backend/test_blacklist.py +++ /dev/null @@ -1,52 +0,0 @@ -import sys -from app.core.token_blacklist import token_blacklist -from app.core.security import verify_token - -def test_blacklist(): - """测试令牌黑名单功能""" - try: - print("=== 测试令牌黑名单功能 ===") - - # 使用之前获取的令牌 - token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3IiwidXNlcm5hbWUiOiJ0ZXN0bWUiLCJlbWFpbCI6InRlc3RtZUBleGFtcGxlLmNvbSIsImV4cCI6MTc2MDE3MjI5OCwidHlwZSI6ImFjY2VzcyJ9.Fp9cZ4rDelm6mpxc0cYqXJJ4ne-xG90QuAx1UNfJBIY" - - # 1. 检查令牌是否在黑名单中 - print("1. 检查令牌是否在黑名单中...") - is_blacklisted = token_blacklist.is_blacklisted(token) - print(f" 令牌在黑名单中: {is_blacklisted}") - - # 2. 验证令牌 - print("2. 验证令牌...") - payload = verify_token(token, "access") - if payload: - print(f" 令牌验证成功,用户ID: {payload.get('sub')}") - else: - print(" 令牌验证失败") - - # 3. 手动将令牌加入黑名单 - print("3. 将令牌加入黑名单...") - token_blacklist.add_token(token) - print(" 令牌已加入黑名单") - - # 4. 再次检查 - print("4. 再次检查令牌是否在黑名单中...") - is_blacklisted = token_blacklist.is_blacklisted(token) - print(f" 令牌在黑名单中: {is_blacklisted}") - - # 5. 再次验证令牌 - print("5. 再次验证令牌...") - payload = verify_token(token, "access") - if payload: - print(f" 令牌验证成功,用户ID: {payload.get('sub')}") - else: - print(" 令牌验证失败(预期结果)") - - print("\n=== 黑名单功能测试完成 ===") - - except Exception as e: - print(f"测试过程出错: {e}") - import traceback - traceback.print_exc() - -if __name__ == "__main__": - test_blacklist() \ No newline at end of file diff --git a/backend/test_db_connection.py b/backend/test_db_connection.py deleted file mode 100644 index 44c12b0..0000000 --- a/backend/test_db_connection.py +++ /dev/null @@ -1,57 +0,0 @@ -import pymysql -from app.core.config import settings - -def test_mysql_connection(): - try: - print(f"正在连接数据库: {settings.DATABASE_URL}") - - # 解析连接字符串 - import re - pattern = r'mysql\+pymysql://([^:]+):([^@]+)@([^:]+):(\d+)/(.+)' - match = re.match(pattern, settings.DATABASE_URL) - - if match: - username, password, host, port, database = match.groups() - print(f"主机: {host}") - print(f"端口: {port}") - print(f"用户: {username}") - print(f"数据库: {database}") - - # 尝试连接 - connection = pymysql.connect( - host=host, - port=int(port), - user=username, - password=password, - database=database, - charset='utf8mb4' - ) - - print("MySQL数据库连接成功!") - - # 测试查询 - with connection.cursor() as cursor: - cursor.execute("SELECT VERSION()") - version = cursor.fetchone() - print(f"MySQL版本: {version[0]}") - - cursor.execute("SHOW TABLES") - tables = cursor.fetchall() - print(f"现有表数量: {len(tables)}") - for table in tables: - print(f"- {table[0]}") - - connection.close() - return True - - else: - print("连接字符串格式错误") - return False - - except Exception as e: - print(f"数据库连接失败: {str(e)}") - print(f"错误类型: {type(e).__name__}") - return False - -if __name__ == "__main__": - test_mysql_connection() \ No newline at end of file diff --git a/backend/test_direct_write.py b/backend/test_direct_write.py deleted file mode 100644 index 4cfbf0b..0000000 --- a/backend/test_direct_write.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python3 -""" -直接测试文件写入,绕过所有业务逻辑 -""" - -import os - -def test_direct_write(): - """直接测试文件写入""" - - print("=== 直接文件写入测试 ===") - - # 测试内容 - test_content = b"Direct write test content - bypassing all logic" - - # 文件路径 - file_path = "uploads/direct_test_write.txt" - - print(f"测试内容大小: {len(test_content)} bytes") - print(f"目标路径: {os.path.abspath(file_path)}") - - # 确保目录存在 - os.makedirs("uploads", exist_ok=True) - - # 方法1: 使用 open 直接写入 - print("\n--- 方法1: 直接 open 写入 ---") - try: - with open(file_path, "wb") as f: - written = f.write(test_content) - f.flush() - os.fsync(f.fileno()) - print(f"写入字节数: {written}") - - if os.path.exists(file_path): - size = os.path.getsize(file_path) - print(f"文件大小: {size} bytes") - - if size == len(test_content): - print("✅ 方法1成功!") - else: - print(f"❌ 方法1失败: 大小不匹配 {size} != {len(test_content)}") - else: - print("❌ 方法1失败: 文件不存在") - - except Exception as e: - print(f"❌ 方法1异常: {e}") - - # 方法2: 使用 Path 写入 - print("\n--- 方法2: 使用 pathlib.Path 写入 ---") - from pathlib import Path - file_path2 = "uploads/path_test_write.txt" - - try: - Path(file_path2).write_bytes(test_content) - - if os.path.exists(file_path2): - size = os.path.getsize(file_path2) - print(f"文件大小: {size} bytes") - - if size == len(test_content): - print("✅ 方法2成功!") - else: - print(f"❌ 方法2失败: 大小不匹配 {size} != {len(test_content)}") - else: - print("❌ 方法2失败: 文件不存在") - - except Exception as e: - print(f"❌ 方法2异常: {e}") - - # 方法3: 检查现有文件 - print("\n--- 方法3: 检查现有损坏的文件 ---") - existing_files = [f for f in os.listdir("uploads") if f.endswith('.txt')] - print(f"现有文本文件: {existing_files}") - - for filename in existing_files[:3]: # 只检查前3个 - file_path = os.path.join("uploads", filename) - try: - size = os.path.getsize(file_path) - print(f"{filename}: {size} bytes") - - if size > 0: - with open(file_path, 'rb') as f: - content = f.read(min(100, size)) - print(f" 内容预览: {content}") - - except Exception as e: - print(f" 读取错误: {e}") - -if __name__ == "__main__": - test_direct_write() \ No newline at end of file diff --git a/backend/test_file_upload.py b/backend/test_file_upload.py deleted file mode 100644 index 114dac5..0000000 --- a/backend/test_file_upload.py +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/env python3 -""" -测试文件上传功能的脚本 -""" - -import requests -import json -from pathlib import Path - -# API基础URL -BASE_URL = "http://localhost:8000/api/v1" - -def test_file_upload(): - """测试文件上传功能""" - - # 1. 先注册或登录用户获取token - print("1. 测试用户登录...") - login_data = { - "username": "testuser", - "password": "testpass123" - } - - try: - # 尝试登录 - response = requests.post(f"{BASE_URL}/auth/login", json=login_data) - if response.status_code == 200: - result = response.json() - if result.get("success"): - token = result["data"]["tokens"]["access_token"] - print("[OK] 登录成功") - else: - print("[ERROR] 登录失败,尝试注册...") - # 如果登录失败,先注册 - register_data = { - "username": "testuser", - "email": "test@example.com", - "password": "testpass123" - } - register_response = requests.post(f"{BASE_URL}/auth/register", json=register_data) - if register_response.status_code == 201: - register_result = register_response.json() - if register_result.get("success"): - token = register_result["data"]["tokens"]["access_token"] - print("✓ 注册成功") - else: - print(f"✗ 注册失败: {register_result}") - return - else: - print(f"✗ 注册请求失败: {register_response.status_code}") - return - - # 注册后再次登录 - login_response = requests.post(f"{BASE_URL}/auth/login", json=login_data) - if login_response.status_code == 200: - login_result = login_response.json() - if login_result.get("success"): - token = login_result["data"]["tokens"]["access_token"] - print("✓ 登录成功") - else: - print(f"登录请求失败: {response.status_code}") - return - - except Exception as e: - print(f"认证过程出错: {e}") - return - - # 设置认证头 - headers = { - "Authorization": f"Bearer {token}" - } - - # 2. 创建测试文件 - print("\n2. 创建测试文件...") - test_file_path = "test_file.txt" - test_content = "这是一个测试文件内容\nHello, World!\n测试文件上传功能" - - try: - with open(test_file_path, "w", encoding="utf-8") as f: - f.write(test_content) - print(f"✓ 创建测试文件: {test_file_path}") - except Exception as e: - print(f"✗ 创建测试文件失败: {e}") - return - - # 3. 测试文件上传 - print("\n3. 测试文件上传...") - try: - with open(test_file_path, "rb") as f: - files = { - "file": (test_file_path, f, "text/plain") - } - data = { - "description": "测试文件描述", - "tags": "测试,文件,上传", - "is_public": "false" - } - - upload_response = requests.post( - f"{BASE_URL}/files/upload", - headers=headers, - files=files, - data=data - ) - - if upload_response.status_code == 201: - upload_result = upload_response.json() - if upload_result.get("success"): - file_info = upload_result["data"]["file"] - print(f"✓ 文件上传成功!") - print(f" 文件ID: {file_info['id']}") - print(f" 文件名: {file_info['original_filename']}") - print(f" 文件大小: {file_info['file_size']} 字节") - - # 保存文件ID用于后续测试 - file_id = file_info["id"] - else: - print(f"✗ 文件上传失败: {upload_result}") - return - else: - print(f"✗ 文件上传请求失败: {upload_response.status_code}") - print(f"响应内容: {upload_response.text}") - return - - except Exception as e: - print(f"✗ 文件上传过程出错: {e}") - return - - # 4. 测试获取文件列表 - print("\n4. 测试获取文件列表...") - try: - list_response = requests.get( - f"{BASE_URL}/files/list", - headers=headers - ) - - if list_response.status_code == 200: - list_result = list_response.json() - if list_result.get("success"): - files_list = list_result["data"]["files"] - pagination = list_result["data"]["pagination"] - print(f"✓ 获取文件列表成功!") - print(f" 文件数量: {len(files_list)}") - print(f" 总数: {pagination['total']}") - for file_item in files_list: - print(f" - {file_item['original_filename']} ({file_item['file_size']} 字节)") - else: - print(f"✗ 获取文件列表失败: {list_result}") - else: - print(f"✗ 获取文件列表请求失败: {list_response.status_code}") - - except Exception as e: - print(f"✗ 获取文件列表过程出错: {e}") - - # 5. 测试获取存储信息 - print("\n5. 测试获取存储信息...") - try: - storage_response = requests.get( - f"{BASE_URL}/files/storage/info", - headers=headers - ) - - if storage_response.status_code == 200: - storage_result = storage_response.json() - if storage_result.get("success"): - storage_info = storage_result["data"] - print(f"✓ 获取存储信息成功!") - print(f" 总配额: {storage_info['total_quota']} 字节") - print(f" 已使用: {storage_info['used_space']} 字节") - print(f" 可用空间: {storage_info['available_space']} 字节") - print(f" 使用百分比: {storage_info['usage_percentage']:.2f}%") - print(f" 文件数量: {storage_info['file_count']}") - else: - print(f"✗ 获取存储信息失败: {storage_result}") - else: - print(f"✗ 获取存储信息请求失败: {storage_response.status_code}") - - except Exception as e: - print(f"✗ 获取存储信息过程出错: {e}") - - # 6. 测试文件下载 - print("\n6. 测试文件下载...") - try: - download_response = requests.get( - f"{BASE_URL}/files/{file_id}/download", - headers=headers - ) - - if download_response.status_code == 200: - print(f"✓ 文件下载成功!") - print(f" 下载内容长度: {len(download_response.content)} 字节") - # 保存下载的文件 - downloaded_file_path = "downloaded_test_file.txt" - with open(downloaded_file_path, "wb") as f: - f.write(download_response.content) - print(f" 已保存为: {downloaded_file_path}") - else: - print(f"✗ 文件下载请求失败: {download_response.status_code}") - - except Exception as e: - print(f"✗ 文件下载过程出错: {e}") - - # 7. 清理测试文件 - print("\n7. 清理测试文件...") - try: - Path(test_file_path).unlink(missing_ok=True) - Path("downloaded_test_file.txt").unlink(missing_ok=True) - print("✓ 清理完成") - except Exception as e: - print(f"✗ 清理过程出错: {e}") - - print("\n🎉 文件存储功能测试完成!") - -if __name__ == "__main__": - test_file_upload() \ No newline at end of file diff --git a/backend/test_files_simple.py b/backend/test_files_simple.py deleted file mode 100644 index b898cc0..0000000 --- a/backend/test_files_simple.py +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env python3 -""" -简化版文件API测试脚本 -""" - -import requests -import json - -# API基础URL -BASE_URL = "http://localhost:8000/api/v1" - -# 固定用户ID -USER_ID = 8 - -def test_file_upload(): - """测试文件上传""" - test_content = "Hello World! 这是测试文件内容。" - - try: - files = { - "file": ("test.txt", test_content.encode("utf-8"), "text/plain") - } - data = { - "user_id": USER_ID, - "description": "测试文件上传", - "tags": "test,upload", - "is_public": "false" - } - - response = requests.post( - f"{BASE_URL}/files/upload", - files=files, - data=data - ) - - print(f"上传状态码: {response.status_code}") - print(f"上传响应: {response.text}") - - if response.status_code == 201: - result = response.json() - if result.get("success"): - file_info = result["data"]["file"] - print(f"上传成功! 文件ID: {file_info['id']}") - return file_info['id'] - - return None - except Exception as e: - print(f"上传出错: {e}") - return None - -def test_file_list(): - """测试获取文件列表""" - try: - data = { - "user_id": USER_ID, - "page": 1, - "size": 20 - } - - response = requests.post( - f"{BASE_URL}/files/list", - json=data - ) - - print(f"列表状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - files = result["data"]["files"] - print(f"文件数量: {len(files)}") - for f in files: - print(f" - {f['original_filename']} (ID: {f['id']}, 大小: {f['file_size']} bytes)") - return files - - except Exception as e: - print(f"获取列表出错: {e}") - return [] - -def test_storage_info(): - """测试存储信息""" - try: - data = { - "user_id": USER_ID - } - - response = requests.post( - f"{BASE_URL}/files/storage/info", - json=data - ) - - print(f"存储信息状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - info = result["data"] - print(f"存储信息:") - print(f" 总配额: {info['total_quota']} bytes") - print(f" 已使用: {info['used_space']} bytes") - print(f" 可用空间: {info['available_space']} bytes") - print(f" 使用百分比: {info['usage_percentage']:.2f}%") - print(f" 文件数量: {info['file_count']}") - - except Exception as e: - print(f"获取存储信息出错: {e}") - -def test_file_info(file_id): - """测试获取文件信息""" - try: - data = { - "user_id": USER_ID, - "file_id": file_id - } - - response = requests.post( - f"{BASE_URL}/files/info", - json=data - ) - - print(f"文件信息状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - info = result["data"] - print(f"文件信息:") - print(f" 文件名: {info['original_filename']}") - print(f" 大小: {info['file_size']} bytes") - print(f" MIME类型: {info['mime_type']}") - print(f" 是否图片: {info['is_image']}") - print(f" 是否文档: {info['is_document']}") - print(f" 格式化大小: {info['size_formatted']}") - - except Exception as e: - print(f"获取文件信息出错: {e}") - -def test_file_delete(file_id): - """测试删除文件""" - try: - data = { - "user_id": USER_ID, - "file_id": file_id - } - - response = requests.post( - f"{BASE_URL}/files/delete", - json=data - ) - - print(f"删除状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - print("文件删除成功") - else: - print(f"删除失败: {result}") - else: - print(f"删除请求失败: {response.text}") - - except Exception as e: - print(f"删除文件出错: {e}") - -if __name__ == "__main__": - print(f"开始测试文件API (用户ID: {USER_ID})...") - - # 1. 测试存储信息 - print("\n=== 测试存储信息 ===") - test_storage_info() - - # 2. 上传文件 - print("\n=== 测试文件上传 ===") - file_id = test_file_upload() - - # 3. 获取文件列表 - print("\n=== 测试文件列表 ===") - files = test_file_list() - - # 4. 获取文件信息 - if file_id: - print("\n=== 测试文件信息 ===") - test_file_info(file_id) - - # 5. 删除文件 - print("\n=== 测试文件删除 ===") - test_file_delete(file_id) - - # 6. 再次检查文件列表和存储信息 - print("\n=== 最终检查 ===") - test_file_list() - test_storage_info() - - print("\n测试完成!") \ No newline at end of file diff --git a/backend/test_loguru.py b/backend/test_loguru.py deleted file mode 100644 index de24a5f..0000000 --- a/backend/test_loguru.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from loguru import logger -import sys -import os - -# 移除默认处理器 -logger.remove() - -# 添加控制台输出 -logger.add( - sys.stdout, - format="{time:HH:mm:ss} | {level: <8} | {message}", - level="INFO", - colorize=True -) - -print("=== Loguru Test ===") -logger.info("This is an info message") -logger.success("This is a success message") -logger.warning("This is a warning message") -logger.error("This is an error message") -logger.debug("This debug message won't show (level too high)") - -# 测试中文输出 -logger.info("中文测试输出 🚀") -logger.success("上传文件成功 ✅") -logger.error("下载文件失败 ❌") - -print("Test completed!") \ No newline at end of file diff --git a/backend/test_loguru_simple.py b/backend/test_loguru_simple.py deleted file mode 100644 index b25fb43..0000000 --- a/backend/test_loguru_simple.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from loguru import logger -import sys - -# 创建安全流处理器 -class SafeStreamHandler: - def __init__(self, stream): - self.stream = stream - - def write(self, message): - try: - self.stream.write(message) - except UnicodeEncodeError: - clean_message = message.encode('utf-8', errors='ignore').decode('utf-8') - self.stream.write(clean_message) - - def flush(self): - self.stream.flush() - -# 配置loguru -logger.remove() -logger.add( - SafeStreamHandler(sys.stdout), - format="{time:HH:mm:ss} | {level: <8} | {message}", - level="INFO" -) - -print("=== Loguru Simple Test ===") -logger.info("Server starting...") -logger.info("Test upload file") -logger.success("Upload completed") -logger.warning("File already exists") -logger.error("Download failed") -print("Test completed!") \ No newline at end of file diff --git a/backend/test_output.py b/backend/test_output.py deleted file mode 100644 index 35691ee..0000000 --- a/backend/test_output.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import sys -import os - -print("=== 测试输出 ===", flush=True) -print("Python版本:", sys.version, flush=True) -print("当前工作目录:", os.getcwd(), flush=True) -print("stdout编码:", sys.stdout.encoding, flush=True) -print("stderr编码:", sys.stderr.encoding, flush=True) - -import logging - -# 配置日志 -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[logging.StreamHandler(sys.stdout)] -) - -logger = logging.getLogger(__name__) -logger.info("这是一条测试日志") -logger.warning("这是一条警告日志") - -print("测试完成!", flush=True) - -# 写入文件测试 -with open("test_log.txt", "w", encoding="utf-8") as f: - f.write("测试文件写入\n") - f.write(f"时间: {os.times()}\n") - -print("文件写入完成", flush=True) \ No newline at end of file diff --git a/backend/test_post_api.py b/backend/test_post_api.py deleted file mode 100644 index 93f5eea..0000000 --- a/backend/test_post_api.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env python3 -""" -测试POST文件API的脚本 -""" - -import requests -import json - -# API基础URL -BASE_URL = "http://localhost:8000/api/v1" - -def create_test_user(): - """创建测试用户""" - register_data = { - "username": "testuser", - "email": "test@example.com", - "password": "TestPass123!", - "confirm_password": "TestPass123!" - } - - try: - print("创建测试用户...") - reg_response = requests.post(f"{BASE_URL}/auth/register", json=register_data) - print(f"注册状态码: {reg_response.status_code}") - - if reg_response.status_code == 201: - reg_result = reg_response.json() - if reg_result.get("success"): - user_id = reg_result["data"]["user"]["id"] - print(f"用户创建成功,ID: {user_id}") - return user_id - else: - print(f"注册失败: {reg_result}") - else: - print(f"注册请求失败,状态码: {reg_response.status_code}") - - # 如果注册失败,尝试获取现有用户 - print("尝试获取现有用户...") - login_data = { - "username": "testuser", - "password": "TestPass123!" - } - login_response = requests.post(f"{BASE_URL}/auth/login", json=login_data) - if login_response.status_code == 200: - login_result = login_response.json() - if login_result.get("success"): - user_id = login_result["data"]["user"]["id"] - print(f"登录成功,用户ID: {user_id}") - return user_id - - return None - except Exception as e: - print(f"创建用户出错: {e}") - return None - -def test_file_upload(user_id): - """测试文件上传""" - test_content = "Hello World! 测试文件上传内容" - - try: - files = { - "file": ("test.txt", test_content.encode("utf-8"), "text/plain") - } - data = { - "user_id": user_id, - "description": "测试文件上传", - "tags": "test,upload,api", - "is_public": "false" - } - - response = requests.post( - f"{BASE_URL}/files/upload", - files=files, - data=data - ) - - print(f"上传状态码: {response.status_code}") - print(f"上传响应: {response.text}") - - if response.status_code == 201: - result = response.json() - if result.get("success"): - file_info = result["data"]["file"] - print(f"上传成功! 文件ID: {file_info['id']}") - print(f"文件名: {file_info['original_filename']}") - print(f"文件大小: {file_info['file_size']} bytes") - return file_info['id'] - - return None - except Exception as e: - print(f"上传出错: {e}") - return None - -def test_file_list(user_id): - """测试获取文件列表""" - try: - data = { - "user_id": user_id, - "page": 1, - "size": 20 - } - - response = requests.post( - f"{BASE_URL}/files/list", - json=data - ) - - print(f"列表状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - files = result["data"]["files"] - pagination = result["data"]["pagination"] - print(f"文件数量: {len(files)}") - print(f"总数: {pagination['total']}") - for f in files: - print(f" - {f['original_filename']} ({f['file_size']} bytes)") - print(f" ID: {f['id']}, 创建时间: {f['created_at']}") - - except Exception as e: - print(f"获取列表出错: {e}") - -def test_file_info(user_id, file_id): - """测试获取文件信息""" - try: - data = { - "user_id": user_id, - "file_id": file_id - } - - response = requests.post( - f"{BASE_URL}/files/info", - json=data - ) - - print(f"文件信息状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - info = result["data"] - print(f"文件信息:") - print(f" 文件名: {info['original_filename']}") - print(f" 大小: {info['file_size']} bytes") - print(f" MIME类型: {info['mime_type']}") - print(f" 是否图片: {info['is_image']}") - print(f" 是否文档: {info['is_document']}") - print(f" 文件扩展名: {info['file_extension']}") - print(f" 格式化大小: {info['size_formatted']}") - - except Exception as e: - print(f"获取文件信息出错: {e}") - -def test_storage_info(user_id): - """测试存储信息""" - try: - data = { - "user_id": user_id - } - - response = requests.post( - f"{BASE_URL}/files/storage/info", - json=data - ) - - print(f"存储信息状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - info = result["data"] - print(f"存储信息:") - print(f" 总配额: {info['total_quota']} bytes") - print(f" 已使用: {info['used_space']} bytes") - print(f" 可用空间: {info['available_space']} bytes") - print(f" 使用百分比: {info['usage_percentage']:.2f}%") - print(f" 文件数量: {info['file_count']}") - - except Exception as e: - print(f"获取存储信息出错: {e}") - -def test_file_update(user_id, file_id): - """测试更新文件信息""" - try: - data = { - "user_id": user_id, - "file_id": file_id - } - - update_data = { - "description": "更新后的文件描述", - "tags": "updated,test", - "is_public": True - } - - response = requests.post( - f"{BASE_URL}/files/update", - json=data, - params=update_data - ) - - print(f"更新文件状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - file_info = result["data"]["file"] - print(f"文件更新成功:") - print(f" 描述: {file_info['description']}") - print(f" 标签: {file_info['tags']}") - print(f" 是否公开: {file_info['is_public']}") - - except Exception as e: - print(f"更新文件出错: {e}") - -def test_file_download(user_id, file_id): - """测试文件下载""" - try: - data = { - "user_id": user_id, - "file_id": file_id - } - - response = requests.post( - f"{BASE_URL}/files/download", - json=data - ) - - print(f"下载状态码: {response.status_code}") - - if response.status_code == 200: - print(f"下载成功! 内容长度: {len(response.content)} bytes") - print(f"下载内容: {response.text[:100]}...") # 显示前100个字符 - else: - print(f"下载失败: {response.text}") - - except Exception as e: - print(f"下载出错: {e}") - -def test_file_delete(user_id, file_id): - """测试删除文件""" - try: - data = { - "user_id": user_id, - "file_id": file_id - } - - response = requests.post( - f"{BASE_URL}/files/delete", - json=data - ) - - print(f"删除状态码: {response.status_code}") - - if response.status_code == 200: - result = response.json() - if result.get("success"): - print("文件删除成功") - else: - print(f"删除失败: {result}") - else: - print(f"删除请求失败: {response.text}") - - except Exception as e: - print(f"删除文件出错: {e}") - -if __name__ == "__main__": - print("开始测试POST文件API...") - - # 1. 创建测试用户 - user_id = create_test_user() - if not user_id: - print("无法创建或获取用户,退出测试") - exit(1) - - # 2. 上传文件 - print("\n=== 测试文件上传 ===") - file_id = test_file_upload(user_id) - if not file_id: - print("文件上传失败,继续其他测试") - - # 3. 获取文件列表 - print("\n=== 测试文件列表 ===") - test_file_list(user_id) - - # 4. 获取存储信息 - print("\n=== 测试存储信息 ===") - test_storage_info(user_id) - - # 5. 获取文件信息 - if file_id: - print("\n=== 测试文件信息 ===") - test_file_info(user_id, file_id) - - # 6. 更新文件信息 - print("\n=== 测试文件更新 ===") - test_file_update(user_id, file_id) - - # 7. 下载文件 - print("\n=== 测试文件下载 ===") - test_file_download(user_id, file_id) - - # 8. 删除文件 - print("\n=== 测试文件删除 ===") - test_file_delete(user_id, file_id) - - print("\n测试完成!") \ No newline at end of file diff --git a/backend/test_server_8080.sh b/backend/test_server_8080.sh deleted file mode 100644 index 5a2061d..0000000 --- a/backend/test_server_8080.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash -# 测试服务器API连通性的脚本 - -echo "=== 测试云盘应用API ===" -echo "目标地址: http://localhost:8080" -echo "==================================" - -# 检查服务器是否运行 -echo "1. 检查服务器状态..." - -# 使用curl测试连接 -if curl -s http://localhost:8080/ > /dev/null; then - echo "✅ 服务器正在运行" -else - echo "❌ 服务器未运行,请先启动服务器:" - echo "cd /www/wwwroot/云盘后台/backend && python3 server_no_loguru.py" - exit 1 -fi - -echo "" -echo "2. 测试API端点..." - -# 测试根路径 -echo "测试根路径: http://localhost:8080/" -root_response=$(curl -s http://localhost:8000/ 2>/dev/null) -if [ $? -eq 0 ]; then - echo "✅ 根路径响应正常" -else - echo "❌ 根路径无响应" -fi - -# 测试健康检查 -echo "测试健康检查: http://localhost:8080/api/v1/health" -health_response=$(curl -s http://localhost:8080/api/v1/health 2>/dev/null) -if [ $? -eq 0 ]; then - echo "✅ API健康检查正常" - echo "响应内容: $health_response" -else - echo "❌ API健康检查无响应" -fi - -# 测试API文档 -echo "测试API文档: http://localhost:8080/docs" -docs_response=$(curl -s -I http://localhost:8080/docs 2>/dev/null) -if [ $? -eq 0 ]; then - echo "✅ API文档可访问" -else - echo "❌ API文档无法访问" -fi - -# 测试测试端点 -echo "测试端点: http://localhost:8080/test" -test_response=$(curl -s http://localhost:8080/test 2>/dev/null) -if [ $? -eq 0 ]; then - echo "✅ 测试端点正常" - echo "响应内容: $test_response" -else - echo "❌ 测试端点无响应" -fi - -echo "" -echo "3. 详细测试..." - -# 详细测试多个端点 -endpoints=( - "http://localhost:8080/" - "http://localhost:8080/health" - "http://localhost:8080/api/v1/health" - "http://localhost:8080/test" - "http://localhost:8080/openapi.json" -) - -success_count=0 -total_count=${#endpoints[@]} - -for endpoint in "${endpoints[@]}"; do - echo -n "Testing $endpoint ... " - - response=$(curl -s "$endpoint" 2>/dev/null) - http_code=$(curl -s -o /dev/null -w "%{http_code}" "$endpoint" 2>/dev/null) - - if [ "$http_code" = "200" ]; then - echo "✅ (200)" - success_count=$((success_count + 1)) - else - echo "❌ ($http_code)" - fi -done - -echo "" -echo "==================================" -echo "测试结果汇总:" -echo "总测试数: $total_count" -echo "成功: $success_count" -echo "失败: $((total_count - success_count))" -echo "成功率: $((success_count * 100 / total_count))%" - -if [ $success_count -eq $total_count ]; then - echo "" - echo "🎉 所有API测试通过!" - echo "" - echo "📋 可访问的URL:" - echo " http://localhost:8080/ (根路径)" - echo " http://localhost:8080/docs (Swagger UI)" - echo " http://localhost:8080/redoc (ReDoc)" - echo " http://localhost:8080/api/v1/health (健康检查)" - echo "" - echo "✅ 服务器在端口8080上运行正常!" -else - echo "" - echo "⚠️ 有 $((total_count - success_count)) 个测试失败" - echo "请检查服务器状态和配置" -fi - -echo "" -echo "==================================" \ No newline at end of file diff --git a/backend/test_upload_download_api.py b/backend/test_upload_download_api.py deleted file mode 100644 index 00d6493..0000000 --- a/backend/test_upload_download_api.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -接口级上传下载测试 -""" - -import requests -import json -import sys -import io - -# 设置stdout编码为utf-8 -sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') - -BASE_URL = "http://localhost:8000/api/v1" - -def test_upload_download(): - print("=== 测试文件上传下载 ===") - - # 1. 先创建测试用户 - print("1. 创建测试用户...") - register_data = { - "username": "testuser456", - "email": "test456@example.com", - "password": "Test123456!", - "confirm_password": "Test123456!" - } - - try: - response = requests.post(f"{BASE_URL}/auth/register", json=register_data) - print(f"注册响应状态: {response.status_code}") - print(f"注册响应内容: {response.text}") - - if response.status_code == 201: - user_id = response.json()["data"]["user"]["id"] - print(f"[OK] 用户创建成功,ID: {user_id}") - else: - # 创建另一个用户 - register_data = { - "username": f"testuser{hash('test') % 10000}", - "email": f"test{hash('test') % 10000}@example.com", - "password": "Test123456!", - "confirm_password": "Test123456!" - } - response = requests.post(f"{BASE_URL}/auth/register", json=register_data) - if response.status_code == 201: - user_id = response.json()["data"]["user"]["id"] - print(f"[OK] 新用户创建成功,ID: {user_id}") - else: - print(f"[ERROR] 用户创建失败") - return - except Exception as e: - print(f"[ERROR] 请求异常: {e}") - return - - # 2. 上传文件 - print("\n2. 上传测试文件...") - test_content = "这是测试文件内容\nTest file content\n你好世界!" - - files = {'file': ('test.txt', test_content, 'text/plain')} - data = { - 'user_id': str(user_id), - 'description': '测试文件', - 'tags': 'test', - 'is_public': 'false' - } - - try: - upload_resp = requests.post(f"{BASE_URL}/files/upload", files=files, data=data) - print(f"上传状态码: {upload_resp.status_code}") - print(f"上传响应: {upload_resp.text}") - - if upload_resp.status_code == 201: - file_id = upload_resp.json()["data"]["file"]["id"] - print(f"[OK] 上传成功,文件ID: {file_id}") - else: - print("[ERROR] 上传失败") - return - except Exception as e: - print(f"[ERROR] 上传异常: {e}") - return - - # 3. 下载文件 - print(f"\n3. 下载文件 ID: {file_id}...") - download_data = { - "file_id": file_id, - "user_id": user_id - } - - try: - download_resp = requests.post(f"{BASE_URL}/files/download", json=download_data) - print(f"下载状态码: {download_resp.status_code}") - print(f"下载响应头: {dict(download_resp.headers)}") - - if download_resp.status_code == 200: - downloaded_content = download_resp.text - print(f"[OK] 下载成功") - print(f"下载内容: {downloaded_content}") - print(f"内容长度: {len(downloaded_content)}") - - # 验证内容 - if test_content == downloaded_content: - print("[OK] 内容一致") - else: - print("[ERROR] 内容不一致") - print(f"原始: {repr(test_content)}") - print(f"下载: {repr(downloaded_content)}") - else: - print(f"[ERROR] 下载失败: {download_resp.text}") - except Exception as e: - print(f"[ERROR] 下载异常: {e}") - -if __name__ == "__main__": - test_upload_download() \ No newline at end of file diff --git a/backend/uninstall.sh b/backend/uninstall.sh deleted file mode 100644 index 515da38..0000000 --- a/backend/uninstall.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash -# 云盘后端服务卸载脚本 - -set -e - -# 配置变量 -SERVICE_NAME="cloud-drive" -SERVICE_USER="cloud-drive" -INSTALL_DIR="/opt/cloud-drive" - -echo "=== 云盘后端服务卸载脚本 ===" - -# 检查是否为root用户 -if [ "$EUID" -ne 0 ]; then - echo "错误: 请使用root权限运行此脚本" - exit 1 -fi - -# 停止并禁用服务 -echo "停止服务..." -if systemctl is-active --quiet "$SERVICE_NAME"; then - systemctl stop "$SERVICE_NAME" - echo "✓ 服务已停止" -fi - -echo "禁用服务..." -if systemctl is-enabled --quiet "$SERVICE_NAME"; then - systemctl disable "$SERVICE_NAME" - echo "✓ 服务已禁用" -fi - -# 删除systemd服务文件 -echo "删除systemd服务..." -if [ -f "/etc/systemd/system/$SERVICE_NAME.service" ]; then - rm -f "/etc/systemd/system/$SERVICE_NAME.service" - systemctl daemon-reload - echo "✓ systemd服务文件已删除" -fi - -# 删除防火墙规则 -echo "删除防火墙规则..." -if command -v firewall-cmd &> /dev/null; then - firewall-cmd --permanent --remove-port=8000/tcp 2>/dev/null || true - firewall-cmd --reload 2>/dev/null || true - echo "✓ 防火墙规则已删除 (firewalld)" -elif command -v ufw &> /dev/null; then - ufw delete allow 8000/tcp 2>/dev/null || true - echo "✓ 防火墙规则已删除 (ufw)" -fi - -# 删除日志轮转配置 -echo "删除日志轮转配置..." -if [ -f "/etc/logrotate.d/cloud-drive" ]; then - rm -f "/etc/logrotate.d/cloud-drive" - echo "✓ 日志轮转配置已删除" -fi - -# 询问是否删除数据 -echo "" -read -p "是否删除所有数据和配置文件?(y/N): " -n 1 -r -echo -if [[ $REPLY =~ ^[Yy]$ ]]; then - # 删除安装目录 - echo "删除安装目录..." - if [ -d "$INSTALL_DIR" ]; then - rm -rf "$INSTALL_DIR" - echo "✓ 安装目录已删除" - fi - - # 删除服务用户 - echo "删除服务用户..." - if id "$SERVICE_USER" &>/dev/null; then - userdel "$SERVICE_USER" 2>/dev/null || true - echo "✓ 服务用户已删除" - fi - - echo "✓ 所有数据已删除" -else - echo "保留数据目录: $INSTALL_DIR" - echo "如需手动删除,请运行: rm -rf $INSTALL_DIR" -fi - -echo "" -echo "=== 卸载完成 ===" -echo "云盘后端服务已从系统中完全移除" \ No newline at end of file diff --git a/backend/working_server.py b/backend/working_server.py deleted file mode 100644 index cc731f5..0000000 --- a/backend/working_server.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python3 -print("🚀 启动云盘应用服务器...") - -# 检查Python环境 -import sys -print(f"Python版本: {sys.version}") - -# 尝试导入FastAPI -try: - from fastapi import FastAPI - from fastapi.middleware.cors import CORSMiddleware - import uvicorn - print("✅ FastAPI依赖可用") - - # 创建FastAPI应用 - app = FastAPI( - title="云盘应用 API", - description="现代化的云存储Web应用后端API", - version="1.0.0", - docs_url="/docs", - redoc_url="/redoc" - ) - - # 添加CORS中间件 - app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - - # 定义路由 - @app.get("/") - async def root(): - return { - "message": "云盘应用 API", - "version": "1.0.1", - "docs": "/docs", - "health": "/api/v1/health" - } - - @app.get("/health") - async def health(): - return {"status": "healthy"} - - @app.get("/api/v1/health") - async def api_health(): - import time - return { - "status": "healthy", - "timestamp": time.time(), - "version": "1.0.0" - } - - @app.get("/test") - async def test(): - return {"test": "ok", "server": "working"} - - # 尝试导入app模块以提供完整功能 - try: - from app.core.config import settings - print("✅ 完整app模块可用") - mode = "full" - except ImportError: - print("⚠️ 使用简化模式") - mode = "simplified" - - @app.get("/info") - async def info(): - return { - "mode": mode, - "python_version": str(sys.version), - "status": "running" - } - - print("=" * 50) - print("📍 服务器地址:") - print(" http://localhost:8080") - print(" http://localhost:8080/docs") - print(" http://localhost:8080/api/v1/health") - print("=" * 50) - print("按 Ctrl+C 停止服务") - print() - - # 启动服务器 - uvicorn.run( - app, - host="0.0.0.0", - port=8080, - reload=False, - access_log=True, - log_level="info" - ) - -except ImportError as e: - print(f"❌ 依赖导入失败: {e}") - print("请运行: pip install fastapi uvicorn") - sys.exit(1) -except Exception as e: - print(f"❌ 启动失败: {e}") - sys.exit(1) \ No newline at end of file diff --git a/final_test.txt b/final_test.txt deleted file mode 100644 index 77a64d9..0000000 --- a/final_test.txt +++ /dev/null @@ -1,3 +0,0 @@ -这是最终测试文件,用于验证文件上传修复完全成功。 -时间戳:2025-10-13 15:03 -内容:唯一内容,确保不会触发去重机制。 \ No newline at end of file diff --git a/frontend-test-new.txt b/frontend-test-new.txt deleted file mode 100644 index 49d8899..0000000 --- a/frontend-test-new.txt +++ /dev/null @@ -1,6 +0,0 @@ -新的测试文件 - 前后端联调测试 -创建时间: 2025-10-13 -内容包括中文字符和数字:12345 -This is a test file for frontend-backend integration testing. -特殊符号测试:!@#$%^&*() -测试内容完整性验证。 \ No newline at end of file diff --git a/frontend-test.txt b/frontend-test.txt deleted file mode 100644 index af221ef..0000000 --- a/frontend-test.txt +++ /dev/null @@ -1,10 +0,0 @@ -这是一个测试文件,用于验证前后端文件上传功能。 - -内容包括: -- 中文字符测试 -- English characters test -- 数字: 123456 -- 特殊符号: !@#$%^&*() - -创建时间: 2025-10-13 -测试目的: 验证云盘上传下载功能是否正常工作 \ No newline at end of file diff --git a/new_test_0.txt b/new_test_0.txt deleted file mode 100644 index c128c1f..0000000 --- a/new_test_0.txt +++ /dev/null @@ -1 +0,0 @@ -Completely new file content at diff --git a/success_test.txt b/success_test.txt deleted file mode 100644 index a281f4b..0000000 --- a/success_test.txt +++ /dev/null @@ -1,4 +0,0 @@ -最终成功测试文件! -时间:2025-10-13 15:05:30 -内容:这是用来验证文件上传修复成功的测试文件。 -状态:应该能成功上传! \ No newline at end of file diff --git a/test_upload.txt b/test_upload.txt deleted file mode 100644 index 873bba5..0000000 --- a/test_upload.txt +++ /dev/null @@ -1,5 +0,0 @@ -这是一个测试文件,用于验证文件上传功能是否正常工作。 -文件内容包含中文和英文,以及一些特殊字符:!@#$%^&*() - -Created at: 2025-10-13 -Purpose: 测试文件上传修复 \ No newline at end of file diff --git a/test_upload_v2.txt b/test_upload_v2.txt deleted file mode 100644 index 17edd88..0000000 --- a/test_upload_v2.txt +++ /dev/null @@ -1,5 +0,0 @@ -这是第二个测试文件,用于验证文件上传功能完全正常。 -内容与第一个文件不同,所以不会触发去重机制。 - -测试时间:2025-10-13 14:58 -测试状态:验证上传修复是否成功 \ No newline at end of file diff --git a/ultimate_test.txt b/ultimate_test.txt deleted file mode 100644 index ca9afab..0000000 --- a/ultimate_test.txt +++ /dev/null @@ -1 +0,0 @@ -Completely new file content at Mon, Oct 13, 2025 3:13:24 PM diff --git a/unique_test_1760339196.txt b/unique_test_1760339196.txt deleted file mode 100644 index e8f6de3..0000000 --- a/unique_test_1760339196.txt +++ /dev/null @@ -1 +0,0 @@ -Unique content 1760339195