把不需要的测试文件全部删掉

This commit is contained in:
2025-10-14 20:37:18 +08:00
parent 3dc8731c93
commit 1e61e90b3d
81 changed files with 0 additions and 10551 deletions

View File

@@ -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 "$@"

View File

@@ -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 "$@"

View File

@@ -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()

View File

@@ -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/ 目录

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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 进行安装"

View File

@@ -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. 支持文件去重功能")

View File

@@ -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()

View File

@@ -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)

View File

@@ -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()

View File

@@ -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()

View File

@@ -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("创建用户失败")

View File

@@ -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. 下载接口实现逻辑问题")

View File

@@ -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()

View File

@@ -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()

View File

@@ -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=== 调试完成,一切正常 ===")

View File

@@ -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. 检查是否有其他程序占用端口")

View File

@@ -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()

View File

@@ -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❌ 演示失败,无法上传测试文件")

View File

@@ -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()

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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()

View File

@@ -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"

View File

@@ -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源代码部署这最稳定可靠。"

View File

@@ -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"

View File

@@ -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("需要进一步调试文件保存逻辑")

View File

@@ -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"

View File

@@ -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

View File

@@ -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"

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

@@ -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 了解部署说明"

View File

@@ -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"

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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 "=== 构建完成 ==="

View File

@@ -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保持关联和完整性验证。")

View File

@@ -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()

View File

@@ -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()

View File

@@ -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
)

View File

@@ -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()

View File

@@ -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
)

View File

@@ -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("测试完成!")

View File

@@ -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()

View File

@@ -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()

View File

@@ -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 "✅ 测试完成!"

View File

@@ -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)

View File

@@ -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 # 测试环境不使用热重载
)

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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}")

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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测试完成!")

View File

@@ -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="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <level>{message}</level>",
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!")

View File

@@ -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!")

View File

@@ -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)

View File

@@ -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测试完成!")

View File

@@ -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 "=================================="

View File

@@ -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()

View File

@@ -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 "云盘后端服务已从系统中完全移除"

View File

@@ -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)

View File

@@ -1,3 +0,0 @@
这是最终测试文件,用于验证文件上传修复完全成功。
时间戳2025-10-13 15:03
内容:唯一内容,确保不会触发去重机制。

View File

@@ -1,6 +0,0 @@
新的测试文件 - 前后端联调测试
创建时间: 2025-10-13
内容包括中文字符和数字12345
This is a test file for frontend-backend integration testing.
特殊符号测试:!@#$%^&*()
测试内容完整性验证。

View File

@@ -1,10 +0,0 @@
这是一个测试文件,用于验证前后端文件上传功能。
内容包括:
- 中文字符测试
- English characters test
- 数字: 123456
- 特殊符号: !@#$%^&*()
创建时间: 2025-10-13
测试目的: 验证云盘上传下载功能是否正常工作

View File

@@ -1 +0,0 @@
Completely new file content at

View File

@@ -1,4 +0,0 @@
最终成功测试文件!
时间2025-10-13 15:05:30
内容:这是用来验证文件上传修复成功的测试文件。
状态:应该能成功上传!

View File

@@ -1,5 +0,0 @@
这是一个测试文件,用于验证文件上传功能是否正常工作。
文件内容包含中文和英文,以及一些特殊字符:!@#$%^&*()
Created at: 2025-10-13
Purpose: 测试文件上传修复

View File

@@ -1,5 +0,0 @@
这是第二个测试文件,用于验证文件上传功能完全正常。
内容与第一个文件不同,所以不会触发去重机制。
测试时间2025-10-13 14:58
测试状态:验证上传修复是否成功

View File

@@ -1 +0,0 @@
Completely new file content at Mon, Oct 13, 2025 3:13:24 PM

View File

@@ -1 +0,0 @@
Unique content 1760339195