如果你曾经在前端项目里引入 ali-oss,然后看着打包体积飙升,你就会理解我为什么要写这篇文章。

痛点:ali-oss 的"重量级"烦恼

让我们直接看数据:

包 Minified Gzipped
ali-oss (v6.23.0) 675.3 KB 172.2 KB
@aws-sdk/client-s3 (v3.958.0) 394.7 KB 99.0 KB

172KB——这是一个用于上传文件的 SDK 的 gzip 后体积。对于一个只需要生成签名 URL 让用户直接上传到 OSS 的场景,这个代价太大了。

更糟糕的是,ali-oss 承载了太多历史包袱:Browser 和 Node.js 双环境支持、各种边缘 case 的 polyfill、以及一些你可能永远用不到的功能。

转折:发现 OSS 的"隐藏协议"

在尝试自己实现 V4 签名算法(是的,我做了这件事)后,我发现了一个更优雅的解决方案:

阿里云 OSS 官方支持 Amazon S3 兼容 API。

这意味着你可以直接用 AWS 官方的 S3 SDK 来操作阿里云 OSS。不需要魔改,不需要 hack,官方背书。

决策树:什么时候用 S3 SDK?

在决定切换之前,先确认你的使用场景。

✅ 推荐使用 S3 SDK 的场景

  1. 前端直传(Presigned URL)

    • 只需要生成签名 URL,让浏览器直接 PUT/GET 文件
    • 这是最常见的场景,也是 S3 SDK 最大的优势
  2. 基础文件操作

    • 上传、下载、删除、列表
    • 分片上传(Multipart Upload)
  3. 多云架构

    • 需要同时支持 AWS S3、Cloudflare R2、MinIO、阿里云 OSS
    • 一套代码,多云兼容
  4. 追求最小依赖

    • 对 bundle size 敏感的前端项目
    • Serverless 函数(冷启动时间敏感)

⚠️ 仍需使用 ali-oss 的场景

  1. 视频处理

    • 通过 S3 协议调用时,x-oss-process 参数不支持 video/ 类型
    • 只支持 image/ 和 style/ 处理
  2. OSS 特有功能

    • 图片样式管理
    • 部分高级生命周期规则
    • OSS-HDFS 等阿里云特有能力
  3. 遗留系统改造成本高

    • 已有大量 ali-oss 代码,且运行良好
    • 不值得为了省几十 KB 做大规模重构

实战:S3 SDK 连接阿里云 OSS

下面是一个完整的实现示例。

安装依赖

npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner

注意:@aws-sdk/s3-request-presigner 是扩展包,必须配合 @aws-sdk/client-s3 使用。

生成签名 URL

// presign.ts
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

// 创建 S3 客户端,指向阿里云 OSS
const client = new S3Client({
  region: "oss-cn-hangzhou", // 你的 OSS Region
  endpoint: "https://oss-cn-hangzhou.aliyuncs.com", // 关键:指定 OSS Endpoint
  credentials: {
    accessKeyId: "YOUR_ACCESS_KEY_ID",
    secretAccessKey: "YOUR_ACCESS_KEY_SECRET",
  },
  // 阿里云 OSS 仅支持 Virtual-Hosted 风格(默认即是)
  forcePathStyle: false,
});

// 生成上传用的签名 URL
async function getUploadUrl(bucket: string, key: string) {
  const command = new PutObjectCommand({
    Bucket: bucket,
    Key: key,
  });

  const url = await getSignedUrl(client, command, {
    expiresIn: 3600, // 1 小时有效期
  });

  return url;
}

// 生成下载用的签名 URL
async function getDownloadUrl(bucket: string, key: string) {
  const command = new GetObjectCommand({
    Bucket: bucket,
    Key: key,
  });

  return await getSignedUrl(client, command, {
    expiresIn: 3600,
  });
}

关键配置说明

配置项 说明
region OSS 的 Region ID,如 oss-cn-hangzhou
endpoint 完整的 OSS Endpoint URL
forcePathStyle 必须为 false,OSS 仅支持 Virtual-Hosted 风格

已知差异与注意事项

在将 S3 SDK 用于 OSS 时,有几个关键差异需要注意:

1. 仅支持 Virtual-Hosted 请求风格

OSS 不支持 Path-Style 请求。也就是说,URL 必须是:

  • ✅ https://bucket-name.oss-cn-hangzhou.aliyuncs.com/key
  • ❌ https://oss-cn-hangzhou.aliyuncs.com/bucket-name/key

S3 SDK 默认使用 Virtual-Hosted,所以一般不需要特别处理。

2. ETag 大小写

  • OSS 返回的 ETag 是大写
  • S3 返回的 ETag 是小写

如果你的代码依赖 ETag 进行校验,请忽略大小写。

3. 存储类型映射

S3 OSS 对应
STANDARD 标准存储
STANDARD_IA 低频访问
GLACIER 归档存储

4. ACL 支持范围

OSS 在 S3 模式下仅支持以下 ACL:

  • private
  • public-read
  • public-read-write

其他 S3 ACL(如 bucket-owner-full-control)不被支持。

附录:阿里云 OSS S3 兼容 API 完整清单

以下是阿里云官方文档确认支持的 S3 API 操作:

Bucket 操作

操作 支持状态
PutBucket ✅
DeleteBucket ✅
GetBucket (ListObjects) ✅
GetBucketV2 (ListObjectsV2) ✅
GetBucketACL ✅
GetBucketLifecycle ✅
GetBucketLocation ✅
GetBucketLogging ✅
HeadBucket ✅
PutBucketACL ✅
PutBucketLifecycle ✅
PutBucketLogging ✅

Object 操作

操作 支持状态
DeleteObject ✅
DeleteObjects ✅
GetObject ✅
GetObjectACL ✅
HeadObject ✅
PostObject ✅
PutObject ✅
PutObjectCopy ✅
PutObjectACL ✅

Multipart 操作

操作 支持状态
InitiateMultipartUpload ✅
AbortMultipartUpload ✅
CompleteMultipartUpload ✅
ListParts ✅
UploadPart ✅
UploadPartCopy ✅

总结

选择 S3 SDK 如果你:

  • 只需要签名 URL 进行前端直传
  • 追求最小 bundle size
  • 需要多云兼容架构

继续使用 ali-oss 如果你:

  • 需要视频处理 (x-oss-process=video/)
  • 依赖 OSS 特有功能
  • 已有稳定运行的遗留代码

对于大多数现代应用来说,S3 SDK 是更轻量、更通用、更面向未来的选择。毕竟,谁不想让自己的 bundle 瘦身 42% 呢?


参考资料:阿里云 OSS 官方文档 - S3 兼容 API