最稳方案是用oss2库的put_object_from_file:三行代码完成上传,自动分片、断点续传;endpoint须带https://且地域严格匹配;文件夹同步需手动遍历+去重校验,超10万文件应改用ossutil sync。

用 oss2.Bucket.put_object_from_file 同步单个文件最稳
别碰 aliyun-python-sdk-oss,它连 put_object 都要自己拼签名和 HTTP body,SignatureDoesNotMatch 或 InvalidArgument 错误基本都源于此。直接装 oss2:pip install oss2。上传一个本地文件到指定路径,核心就三行:
auth = oss2.Auth('your-access-key-id', 'your-access-key-secret')bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'your-bucket-name')bucket.put_object_from_file('remote/path/file.txt', '/local/path/file.txt')
这个方法自动判断文件大小:小文件直传,大文件分片上传,还带断点续传和重试。注意 endpoint 必须带 https:// 前缀,且地域(如 oss-cn-hangzhou)必须和 bucket 所在地域完全一致,写成 oss-cn-hangzhou.aliyuncs.com(缺协议)会静默失败。
同步整个文件夹需手动遍历 + put_object_from_file
oss2 没有内置的递归 sync 方法,得自己 walk 目录并逐个上传。关键点不是“能不能做”,而是“怎么避免重复上传和漏传”:
- 用
os.walk()获取所有本地文件路径,过滤掉目录和隐藏文件(如.git、__pycache__) - 生成 OSS object key 时,去掉本地根路径前缀,用
os.path.relpath()算相对路径,再把\替换为/(Windows 兼容) - 上传前建议加一层存在性检查:调用
bucket.head_object(object_key)看是否已存在且Last-Modified时间戳一致;但注意——这会额外产生 HEAD 请求,文件多时费用和延迟明显上升 - 如果业务允许最终一致性,跳过检查直接上传更高效;若必须强一致,建议用本地快照(如记录
md5(file)+mtime到 SQLite)做增量比对
百万级文件同步必须用 ossutil sync 命令行
Python 脚本遍历 + 逐个 put_object_from_file 在文件数超 10 万后就会明显变慢,根本原因是单线程串行发起 HTTP 请求,OSS 的并发限制和 Python GIL 双重拖累。此时该切回官方工具:
ossutil sync /local/folder/ oss://bucket-name/remote/ --delete --update
--delete 会清理目标端多余文件,--update 仅上传修改过的文件。但注意:--update 默认靠 Last-Modified 时间比对,若本地文件时间被篡改或 NFS 挂载导致精度丢失,可能漏同步;真要靠内容一致性,得加 --check-md5,但会显著增加本地 CPU 和网络开销。另外,带 --delete 时单次最多处理 100 万个文件,超限报错 over max sync numbers 1000000,得拆成子目录分批跑。
权限和 Endpoint 写错是同步失败最常见原因
AccessKey 至少要有 oss:PutObject 和 oss:ListObjects 权限;如果用了 --delete 或打算删旧文件,还得加 oss:DeleteObject。RAM 子账号务必按最小权限原则配策略,别直接给 AliyunOSSFullAccess。
Endpoint 错误有三种典型表现:
- 写成
http://→ 连接被拒绝或超时(OSS 强制 HTTPS) - 地域不匹配(如 bucket 在杭州却写
oss-cn-beijing)→NoSuchBucket或 403 - 混用内网/外网地址(如 ECS 同地域部署却用公网 endpoint)→ 产生额外流量费且延迟高
控制台里 bucket 的“Endpoint”字段值,复制出来直接用,别手敲、别猜、别从老文档里抄。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











