Ai_GirlFriend/upload_outfit_to_oss_final.py
2026-02-04 18:47:56 +08:00

197 lines
7.6 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
换装图片上传到阿里云 OSS 脚本(最终版 - 仅上传现有的 29 个图片)
"""
import os
import sys
from pathlib import Path
import oss2
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# OSS 配置
ACCESS_KEY_ID = os.getenv('ALIYUN_OSS_ACCESS_KEY_ID')
ACCESS_KEY_SECRET = os.getenv('ALIYUN_OSS_ACCESS_KEY_SECRET')
BUCKET_NAME = os.getenv('ALIYUN_OSS_BUCKET_NAME')
ENDPOINT = os.getenv('ALIYUN_OSS_ENDPOINT', 'https://oss-cn-hangzhou.aliyuncs.com')
CDN_DOMAIN = os.getenv('ALIYUN_OSS_CDN_DOMAIN')
# 图片源目录
SOURCE_DIR = Path('开发/2026年2月4日/Image')
# 文件映射(仅包含实际存在的 29 个文件)
FILE_MAP = {
# 上装 - 女性 (10个)
"女性上衣白色T桖.png": "uploads/outfit/top/white_tshirt.png",
"女性-上装-粉丝短袖.png": "uploads/outfit/top/pink_short_sleeve.png",
"女性-上装-蓝色衬衫.png": "uploads/outfit/top/blue_shirt.png",
"女性-上装-灰色卫衣.png": "uploads/outfit/top/gray_sweatshirt.png",
"女性-上装-收费-蕾丝吊带上衣.png": "uploads/outfit/top/lace_strap.png",
"女性-上装-收费-一字领露肩上衣.png": "uploads/outfit/top/off_shoulder.png",
"女性-上装-收费-露脐短袖.png": "uploads/outfit/top/crop_top.png",
"女性-上装-收费-针织开衫.png": "uploads/outfit/top/knit_cardigan.png",
"女性-上装-收费-小香风外套.png": "uploads/outfit/top/tweed_jacket.png",
"女性-上装-vlp专属-真丝衬衫.png": "uploads/outfit/top/silk_shirt.png",
# 下装 - 女性 (9个)
"女性-下衣-蓝色牛仔裤.png": "uploads/outfit/bottom/blue_jeans.png",
"女性-下衣-黑色短裙.png": "uploads/outfit/bottom/black_skirt.png",
"女性-下衣-白色短裙.png": "uploads/outfit/bottom/white_shorts.png",
"女性-下衣-灰色运动裤.png": "uploads/outfit/bottom/gray_sweatpants.png",
"女性-下衣-A字半身裙.png": "uploads/outfit/bottom/a_line_skirt.png",
"女性-下衣-高腰阔腿裤.png": "uploads/outfit/bottom/high_waist_pants.png",
"女性-下衣-收费-百褶短裙.png": "uploads/outfit/bottom/pleated_skirt.png",
"女性-下衣-收费-破洞牛仔裤.png": "uploads/outfit/bottom/ripped_jeans.png",
"女性-下衣-收费-西装裤.png": "uploads/outfit/bottom/suit_pants.png",
# 连衣裙 - 女性 (10个)
"女性-连衣裙-白色连衣裙.png": "uploads/outfit/dress/white_dress.png",
"女性-连衣裙-碎花连衣裙.png": "uploads/outfit/dress/floral_dress.png",
"女性-连衣裙-黑色小礼服.png": "uploads/outfit/dress/black_dress.png",
"女性-连衣裙-优雅长裙.png": "uploads/outfit/dress/elegant_long_dress.png",
"女性-连衣裙-吊带连衣裙.png": "uploads/outfit/dress/strapless_dress.png",
"女性-连衣裙-JK制服.png": "uploads/outfit/dress/jk_uniform.png",
"女性-连衣裙-汉服.png": "uploads/outfit/dress/hanfu.png",
"女性-连衣裙-洛丽塔.png": "uploads/outfit/dress/lolita.png",
"女性-连衣裙-圣诞服装.png": "uploads/outfit/dress/christmas_dress.png",
"女性-连衣裙-高级定制婚纱.png": "uploads/outfit/dress/custom_wedding_dress.png",
}
def upload_to_oss():
"""上传图片到 OSS"""
# 检查配置
if not all([ACCESS_KEY_ID, ACCESS_KEY_SECRET, BUCKET_NAME]):
print("❌ 错误OSS 配置不完整")
print(f"ACCESS_KEY_ID: {'已配置' if ACCESS_KEY_ID else '未配置'}")
print(f"ACCESS_KEY_SECRET: {'已配置' if ACCESS_KEY_SECRET else '未配置'}")
print(f"BUCKET_NAME: {BUCKET_NAME or '未配置'}")
return False
print("=" * 70)
print(" 换装图片上传到阿里云 OSS最终版")
print("=" * 70)
print()
print(f"📦 OSS Bucket: {BUCKET_NAME}")
print(f"🌐 OSS Endpoint: {ENDPOINT}")
print(f"🚀 CDN Domain: {CDN_DOMAIN or '未配置'}")
print(f"📁 源目录: {SOURCE_DIR}")
print(f"📊 待上传文件数: {len(FILE_MAP)}")
print()
# 初始化 OSS
try:
auth = oss2.Auth(ACCESS_KEY_ID, ACCESS_KEY_SECRET)
# 去掉 endpoint 中的 https://
endpoint_clean = ENDPOINT.replace('https://', '').replace('http://', '')
bucket = oss2.Bucket(auth, endpoint_clean, BUCKET_NAME)
# 测试连接
bucket.get_bucket_info()
print("✓ OSS 连接成功")
print()
except Exception as e:
print(f"❌ OSS 连接失败: {e}")
return False
# 检查源目录
if not SOURCE_DIR.exists():
print(f"❌ 错误:源目录不存在: {SOURCE_DIR}")
return False
# 上传文件
uploaded_count = 0
failed_count = 0
skipped_count = 0
print("开始上传图片...")
print()
for idx, (source_file, oss_object) in enumerate(FILE_MAP.items(), 1):
source_path = SOURCE_DIR / source_file
if not source_path.exists():
print(f"[{idx}/{len(FILE_MAP)}] ⚠️ 跳过(文件不存在): {source_file}")
skipped_count += 1
continue
try:
# 读取文件
with open(source_path, 'rb') as f:
file_data = f.read()
file_size = len(file_data) / 1024 # KB
# 上传到 OSS
bucket.put_object(oss_object, file_data)
# 生成访问 URL
if CDN_DOMAIN:
url = f"{CDN_DOMAIN.rstrip('/')}/{oss_object}"
else:
url = f"https://{BUCKET_NAME}.{endpoint_clean}/{oss_object}"
print(f"[{idx}/{len(FILE_MAP)}] ✓ 已上传: {source_file}")
print(f" 大小: {file_size:.1f} KB")
print(f" OSS: {oss_object}")
print(f" URL: {url}")
print()
uploaded_count += 1
except Exception as e:
print(f"[{idx}/{len(FILE_MAP)}] ❌ 上传失败: {source_file}")
print(f" 错误: {e}")
print()
failed_count += 1
# 统计结果
print("=" * 70)
print(" 上传完成")
print("=" * 70)
print()
print(f"✓ 成功上传: {uploaded_count} 个文件")
if failed_count > 0:
print(f"✗ 上传失败: {failed_count} 个文件")
if skipped_count > 0:
print(f"⚠ 跳过文件: {skipped_count} 个文件")
print()
if uploaded_count > 0:
print("=" * 70)
print(" 下一步操作")
print("=" * 70)
print()
print("1⃣ 执行 SQL 文件导入数据库")
print(" 📄 文件:开发/2026年2月4日/数据填充_换装种类_最终版.sql")
print()
print("2⃣ 重启 Python 服务")
print(" 💻 命令python -m uvicorn lover.main:app --host 0.0.0.0 --port 30101 --reload")
print()
print("3⃣ 测试前端换装功能")
print(" 📱 打开前端应用 → 金币商店 → 查看服装列表")
print()
print("4⃣ 验证图片访问")
print(f" 🌐 示例:{CDN_DOMAIN or f'https://{BUCKET_NAME}.{endpoint_clean}'}/uploads/outfit/top/white_tshirt.png")
print()
return uploaded_count > 0
if __name__ == "__main__":
try:
success = upload_to_oss()
sys.exit(0 if success else 1)
except KeyboardInterrupt:
print("\n\n⚠️ 用户中断")
sys.exit(1)
except Exception as e:
print(f"\n❌ 发生错误: {e}")
import traceback
traceback.print_exc()
sys.exit(1)