优先用 oss.PutObjectFromFile 上传本地文件,小数据或字节切片用 oss.PutObject 并显式设置 ContentLength 和 ContentType;Endpoint 必须为带协议的 Region 地址,凭据需用 RAM 子账号,私有 object 需设 ACL 公开。

oss.PutObject 和 oss.PutObjectFromFile 是最常用的两个上传入口,选哪个取决于数据来源和大小。
小数据(几 MB 以内)直接走 PutObject;大文件或本地路径存在时,无脑用 PutObjectFromFile——它自动分片、流式读、带重试,不爆内存也不卡死。
传字符串或字节切片:用 PutObject,但 Content-Type 和长度不能漏
SDK 不会自动推断 ContentLength,OSS 兼容服务(如 MinIO、COS)会因缺失这个 header 直接返回 400 Bad Request。中文字符串尤其容易翻车:strings.NewReader 算的是 rune 数,不是 UTF-8 字节长度。
- 传字符串:先转
[]byte,再用bytes.NewReader,显式填ContentLength: len(data) - 传 JSON 或 HTML:必须设
oss.ContentType("application/json")或oss.ContentType("text/html; charset=utf-8"),否则浏览器下载乱码或当二进制处理 - 别用
strings.NewReader("中文")—— 它不处理编码,ContentLength会错
传本地文件:优先用 PutObjectFromFile,别自己开 *os.File + PutObject
手动传 *os.File 给 PutObject,SDK 默认一次性读进内存,100MB 文件就可能 OOM;而 PutObjectFromFile 内部按 5MB 分块、边读边传、失败自动重试,还支持断点续传。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 路径含中文或空格?先用
url.PathEscape处理objectName,否则报InvalidObjectName - 文件路径要绝对路径或确保工作目录正确,相对路径容易
open xxx: no such file - 不需要自己
os.Open再包装 reader,PutObjectFromFile全包了
Client 初始化最容易错的三件事:endpoint、协议、凭据来源
oss.New 的第一个参数是 Region Endpoint,不是 Bucket 域名,也不是裸域名。写错就 403 或签名失败,错误信息还不提示具体哪错了。
立即学习“go语言免费学习笔记(深入)”;
- ✅ 正确:
"https://oss-cn-hangzhou.aliyuncs.com"(带 https://,无 bucket 名,无路径) - ❌ 错误:
"http://oss-cn-hangzhou.aliyuncs.com"(HTTP 明文被拒绝) - ❌ 错误:
"oss-cn-hangzhou.aliyuncs.com"(缺协议头,SDK 可能拼成 http://) - ❌ 错误:
"https://my-bucket.oss-cn-hangzhou.aliyuncs.com"(这是 Bucket 域名,不是 Region Endpoint) - 凭据必须来自 RAM 子账号,主账号 AKSK 泄露=交出整个云账号
上传后访问不到?大概率是权限或 URL 拼错了
OSS 默认所有 object 私有,PutObject 上传完,直连 URL 就是 403。不是代码问题,是配置没对上。
- 要公开访问,上传时加
oss.ACL(oss.ACLPublicRead) - ObjectKey 区分大小写,
test.jpg和Test.jpg是两个文件,写错就是 404 - 用了 CDN?缓存可能把旧的 403 响应也存了,得手动刷新
- Bucket Policy 或 RAM 策略 deny 了当前操作,检查是否允许
oss:PutObject到目标 bucket

















