#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 换装图片上传到阿里云 OSS 脚本 """ 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') # 文件映射(源文件名 -> OSS 对象名) FILE_MAP = { # 上装 - 女性 "女性上衣白色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", # 下装 - 女性 "女性-下衣-蓝色牛仔裤.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", # 连衣裙 - 女性 "女性-连衣裙-白色连衣裙.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("=" * 60) print(" 换装图片上传到阿里云 OSS") print("=" * 60) print() print(f"OSS Bucket: {BUCKET_NAME}") print(f"OSS Endpoint: {ENDPOINT}") print(f"CDN Domain: {CDN_DOMAIN or '未配置'}") print(f"源目录: {SOURCE_DIR}") 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) 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 source_file, oss_object in FILE_MAP.items(): source_path = SOURCE_DIR / source_file if not source_path.exists(): print(f"⚠️ 跳过(文件不存在): {source_file}") skipped_count += 1 continue try: # 读取文件 with open(source_path, 'rb') as f: file_data = f.read() # 上传到 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"✓ 已上传: {source_file}") print(f" → {oss_object}") print(f" → {url}") print() uploaded_count += 1 except Exception as e: print(f"❌ 上传失败: {source_file}") print(f" 错误: {e}") print() failed_count += 1 # 统计结果 print("=" * 60) print(" 上传完成") print("=" * 60) print(f"成功上传: {uploaded_count} 个文件") print(f"上传失败: {failed_count} 个文件") print(f"跳过文件: {skipped_count} 个文件") print() if uploaded_count > 0: print("✓ 图片已上传到 OSS") print() print("下一步:") print("1. 执行 SQL 文件导入数据库") print(" 文件:开发/2026年2月4日/数据填充_换装种类_OSS图片.sql") print() print("2. 重启 Python 服务") print(" python -m uvicorn lover.main:app --host 0.0.0.0 --port 30101 --reload") print() print("3. 测试前端换装功能") 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)