Files
c4c-download/batch_download.py

146 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
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
"""批量下载 SAP C4C 附件,从 CSV 读取 Ticket ID并行执行并记录错误日志"""
import subprocess
import sys
import os
import json
import datetime
import csv
import glob
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
# ── 配置 ──────────────────────────────────────────────────────────────────────
TENANT = "https://my300375.c4c.saphybriscloud.cn"
USER = "admin"
PASSWORD = "Xjait.1?"
OUTPUT = "./downloads"
DSM_URL = "http://10.0.10.235:5000"
DSM_USER = "PLM"
DSM_PASS = "123456"
DSM_PATH = "/Newgonow/AU-SPFJ"
WORKERS = 5
SCRIPT = os.path.join(os.path.dirname(__file__), "sap-c4c-AttachmentFolder.py")
ERROR_LOG = os.path.join(os.path.dirname(__file__), "error_log.txt")
DATASOURCE = os.path.join(os.path.dirname(__file__), "datasource")
print_lock = threading.Lock()
# ─────────────────────────────────────────────────────────────────────────────
def get_ticket_ids(limit=10):
ids, seen = [], set()
for csv_file in glob.glob(os.path.join(DATASOURCE, "*.csv")):
with open(csv_file, encoding="utf-8-sig") as f:
reader = csv.reader(f)
next(reader, None)
for row in reader:
if len(row) < 2:
continue
val = row[1].strip()
if val and val not in seen:
seen.add(val)
ids.append(val)
if len(ids) >= limit:
break
if len(ids) >= limit:
break
return ids
def log_error(ticket_id, message):
ts = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(ERROR_LOG, "a", encoding="utf-8") as f:
f.write(f"[{ts}] Ticket {ticket_id}: {message}\n")
def run_ticket(ticket_id, index, total):
with print_lock:
print(f"\n[{index}/{total}] 开始下载 Ticket {ticket_id} ...")
cmd = [
sys.executable, SCRIPT,
"--tenant", TENANT,
"--user", USER,
"--password", PASSWORD,
"--ticket", str(ticket_id),
"--output-dir", os.path.join(OUTPUT, str(ticket_id)),
"--json",
"--dsm-url", DSM_URL,
"--dsm-user", DSM_USER,
"--dsm-password", DSM_PASS,
"--dsm-path", DSM_PATH,
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
# 解析 JSON 输出
try:
data = json.loads(result.stdout)
success = data.get("success", False)
downloaded = len(data.get("downloadedFiles", []))
dsm_uploads = data.get("dsmUpload", [])
ok_uploads = sum(1 for u in dsm_uploads if u.get("success"))
fail_uploads = len(dsm_uploads) - ok_uploads
if success:
with print_lock:
print(f" ✓ [{ticket_id}] 下载 {downloaded} 个文件, DSM 上传 {ok_uploads} 成功 {fail_uploads} 失败")
if fail_uploads:
fails = [u for u in dsm_uploads if not u.get("success")]
for u in fails:
log_error(ticket_id, f"DSM 上传失败: {u.get('file')} - {u.get('error')}")
else:
err = data.get("error", result.stderr or "未知错误")
with print_lock:
print(f" ✗ [{ticket_id}] 失败: {err}")
log_error(ticket_id, err)
except json.JSONDecodeError:
if result.returncode == 0:
with print_lock:
print(f" ✓ [{ticket_id}] 完成")
else:
err = result.stderr.strip() or result.stdout.strip() or "未知错误"
with print_lock:
print(f" ✗ [{ticket_id}] 失败: {err}")
log_error(ticket_id, err)
except subprocess.TimeoutExpired:
msg = "超时 (300s)"
with print_lock:
print(f" ✗ [{ticket_id}] {msg}")
log_error(ticket_id, msg)
except Exception as e:
with print_lock:
print(f" ✗ [{ticket_id}] 异常: {e}")
log_error(ticket_id, str(e))
def main():
print("读取 Ticket ID ...")
ids = get_ticket_ids(10)
if not ids:
print("未找到任何 Ticket ID请检查 datasource 目录")
sys.exit(1)
print(f"{len(ids)} 个 Ticket: {', '.join(ids)}")
# 清空/创建 error_log
open(ERROR_LOG, "w").close()
with ThreadPoolExecutor(max_workers=WORKERS) as executor:
futures = {executor.submit(run_ticket, tid, i, len(ids)): tid
for i, tid in enumerate(ids, 1)}
for future in as_completed(futures):
future.result() # 触发异常传播(已在 run_ticket 内处理)
print("\n全部完成。")
if os.path.getsize(ERROR_LOG) > 0:
print(f"有错误,详见 {ERROR_LOG}")
else:
print("无错误。")
if __name__ == "__main__":
main()