概念

BucketObjectObjectKeyKeyObjectNameRegionEndpointAccessKeyAccessKey IDAccessKey Secret

计费

=+++++

一、存储费

x÷÷x
存储类型 单价
规范-本地冗余 0.12
规范-同城冗余 0.15
低频拜访-本地冗余 0.08
低频拜访-同城冗余 0.10
归档 0.033
冷归档 0.015
81G0.12

二、长期存储费

x÷÷x
存储类型 单价
冷归档 0.12

冷归档文件在冻结期间,须额定领取一笔依照规范存储单价计算的长期存储费用。

三、数据取回费

x
存储类型 单价
规范 0
低频拜访 0.0325
归档 0.06
冷归档 0.03~0.2

四、流量费

x
流量方向 单价
上传 0
内网下载 0
外网下载(0-8) 0.25
外网下载(8-24) 0.50
CDN回源下载 0.15
跨区域复制(中国大陆) 0.50
外网下载(0-8) 0.25
1G10.25

五、申请费

math.Ceil()x
申请类型 规范 低频拜访 归档 冷归档
PUT 0.01 0.1 0.1 0.1
GET 0.01 0.1 0.1 0.1
取回 / / / 0.3 ~ 30
30

六、其他费用

跨区域文件复制流量费、图片处理费、图片压缩费、视频截帧费、标签费、传输减速费、DDoS防护费、元数据管理费、敏感数据保护费等等。

存储类型

规范 + 低频 + 归档 + 冷归档

比照指标 规范 低频 归档 冷归档
最小计量单位 0 64KB 64KB 64KB
最小存储时长 0 30天 60天 180天
拜访提早 0 0 1min 1-12hour
数据取回费用 0 30天 60天 180天

URL

://./://./?签名信息

Bucket

CRUD

BucketCRDU
package main

import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 创立OSSClient实例。
    // yourEndpoint填写Bucket对应的Endpoint。
    // 以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 新增
    err = client.CreateBucket(
        "examplebucket", 
        oss.StorageClass(oss.StorageIA), 
        oss.ACL(oss.ACLPublicRead),
        oss.RedundancyType(oss.RedundancyZRS)
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    /* 
    StorageClass:存储类型。
        StorageStandard=规范存储
        StorageIA=低频拜访
        StorageArchive=归档存储
        StorageColdArchive=冷归档存储
    ACL:拜访权限。
        ACLPrivate=公有
        ACLPublicRead=公共读
        ACLPublicReadWrite=公共读写
    RedundancyType:冗余类型。
        RedundancyLRS=本地冗余
        RedundancyZRS=同城冗余
    */

    // 查问
    marker := ""
    for {
        lsRes, err := client.ListBuckets(oss.Marker(marker))
        if err != nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }

        // 默认状况下一次返回100条记录。
        for _, bucket := range lsRes.Buckets {
            fmt.Println("Bucket: ", bucket.Name)
        }

        if lsRes.IsTruncated {
            marker = lsRes.NextMarker
        } else {
            break
        }
    }

    // 查问Region ID
    regionID, err := client.GetBucketLocation("examplebucket")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    fmt.Println("Bucket Location:", regionID) // oss-cn-shanghai
    /*
        Region ID能够了解为Endpoint的前缀:
        外网Endpoint:oss-cn-shanghai.aliyuncs.com
        内网Endpoint:oss-cn-shanghai-internal.aliyuncs.com
    */

    // 删除
    err = client.DeleteBucket("examplebucket")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}

生命周期

BucketObjectObject

能够基于最初一次批改工夫(Last Modified Time)或最初一次拜访工夫(Last Access Time)创立生命周期规定。

限度 最初一次批改工夫 最初一次拜访工夫
实用场景 拜访模型确定 拜访模型不确定
是否反对删除Object 反对 不反对
存储类型的转换是否可逆 不可逆 可逆

基于最初一次批改工夫

最初一次批改工夫,其实根本能够了解为创立工夫。

这样就能够实现相似「上传N天后删除」或者「上传N天后将存储类型由规范切换为低频拜访」的需要。

一些限度
10002408:0024
package main

import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func Main() {
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 定义规定

    // 前缀为10086的Object将于最初一次批改工夫后的第14天删除
    ruleA := oss.BuildLifecycleRuleByDays("ruleA", "10086", true, 14)

    // 前缀为10010的Object将于2025年10月10日的08:00删除
    ruleB := oss.BuildLifecycleRuleByDate("ruleB", "10010", true, 2025, 10, 10)

    // 前缀为10000的Object的存储类型将于最初一次批改工夫的30天后变更为低频拜访
    ruleC := oss.LifecycleRule{
        ID:     "ruleC",
        Prefix: "10000",
        Status: "Enabled",
        Transitions: []oss.LifecycleTransition{
            {
                Days:         30,
                StorageClass: oss.StorageIA,
            },
        },
    }

    // 设置规定
    err = client.SetBucketLifecycle(
        "examplebucket", []oss.LifecycleRule{ruleA, ruleB, ruleC},
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}

基于最初一次拜访工夫

SDK

Object

类型

Object
上传形式 类型
简略上传 Normal
分片上传 Multipart
追加上传 Appendable

命名

UTF-81 ~ 1024/\

上传和删除

package main

import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func Main() {
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 生成Bucket实例
    bucket, e := client.Bucket("examplebucket")
    if err != nil {
        fmt.Println("Error:", e)
        os.Exit(-1)
    }

    // 上传
    if err = bucket.PutObject("objectKey", file); err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 删除
    if err = bucket.DeleteObject("objectKey"); err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}

访问控制

阿里云提供四种类型的拜访权限控制策略:

类型 束缚对象
RAM Policy OSS服务所属阿里云主账号的RAM
Bucket Policy 所有阿里云主账号的RAM和匿名用户
Bucket ACL Bucket
Object ACL Object

RAM Policy

JSON
{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": [
        "oss:PutObject"
      ],
      "Resource": [
        "acs:oss:*:*:examplebucket"
      ],
      "Condition": {}
    }
  ]
}
VersionStatementEffectActionResourceCondition

能够应用官网的RAM策略编辑器疾速生成RAM策略。

【示例】禁止指定RAM上传Object到Bucket。

RAM Policy
{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": [
        "oss:PutObject"
      ],
      "Resource": [
        "acs:oss:*:*:avatar"
      ],
      "Condition": {}
    }
  ]
}
step2:增加权限策略:

控制台 – RAM访问控制 – 权限治理 – 创立权限策略 – 脚本编辑

step3:为RAM增加权限策略:

控制台 – RAM访问控制 – 身份治理 – 用户 – 增加权限

Bucket Policy

package main

import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func Main() {
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 配置policy(禁止192.168.1.1之外的所有人对examplebucket的所有申请)
    policy := `{
        "Version": "1",
        "Statement": [
            {
                "Principal": ["*"],
                "Effect": "Deny",
                "Action": ["oss:*"],
                "Resource": ["acs:oss:*:*:examplebucket"],
                "Condition": {
                    "NotIpAddress": {
                    "acs:SourceIp": ["192.168.1.1"]
                    }
                }
            }
        ]
    }`

    // 设置
    err = client.SetBucketPolicy("examplebucket", policy)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 查问
    policy, e := client.GetBucketPolicy("examplebucket")
    if e != nil {
        fmt.Println("Error:", e)
        os.Exit(-1)
    }

    // 删除
    err = client.DeleteBucketPolicy("examplebucket")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}

Bucket ACL

package main

import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func Main() {
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 设置examplebucket的权限为公共读
    err = client.SetBucketACL("examplebucket", oss.ACLPublicRead)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 设置examplebucket的权限为公共读写
    err = client.SetBucketACL("examplebucket", oss.ACLPublicReadWrite)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 设置examplebucket的权限为公有
    err = client.SetBucketACL("examplebucket", oss.ACLPrivate)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 查问Bucket ACL
    res, e := client.GetBucketACL("examplebucket")
    if e != nil {
        fmt.Println("Error:", e)
        os.Exit(-1)
    }
}

Object ACL

package main

import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func Main() {
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 生成Bucket实例
    bucket, e := client.Bucket("examplebucket")
    if e != nil {
        fmt.Println("Error:", e)
        os.Exit(-1)
    }

    // 设置exampleobject的权限为公共读
    err = bucket.SetObjectACL("exampleobject", oss.ACLPublicRead)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 设置exampleobject的权限为公共读写
    err = bucket.SetObjectACL("exampleobject", oss.ACLPublicReadWrite)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 设置exampleobject的权限为公有
    err = bucket.SetObjectACL("exampleobject", oss.ACLPrivate)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 设置exampleobject的权限为继承Bucket
    err = bucket.SetObjectACL("exampleobject", oss.ACLDefault)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 查问Object ACL
    res, er := bucket.GetObjectACL("exampleobject")
    if er != nil {
        fmt.Println("Error:", er)
        os.Exit(-1)
    }
}

数据容灾

同城冗余

如果把默认的本地冗余比喻为一份数据存在同一机房内的三个不同硬盘中的话,那么同城冗余就是将数据存在同一数据中心的三个不同机房。

从本地冗余到同城冗余,隔离等级由硬盘级回升到机房级

err = client.CreateBucket(
    "examplebucket", 
    oss.StorageClass(oss.StorageIA), 
    oss.ACL(oss.ACLPublicRead),
    oss.RedundancyType(oss.RedundancyZRS)
)
/* 
    RedundancyType:冗余类型。
    RedundancyLRS=本地冗余
    RedundancyZRS=同城冗余
*/
Bucket

跨城冗余

跨城冗余就是将数据寄存在不同城市的机房。

从同城冗余到跨城冗余,隔离等级由机房级回升到城市级

package main

import (
    "fmt"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
    "os"
)

func main()  {
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    /* 
    指定仅同步复制规定创立后新写入的数据
    不同步源Bucket的历史数据
    且尔后将源Bucket执行的所有操作都将实时同步到指标Bucket
    */
    putXml := `<?xml version="1.0" encoding="UTF-8"?>
    <ReplicationConfiguration>
      <Rule>
        <PrefixSet>
            <! --指定待复制Object的前缀prefix_1和prefix_2。指定Prefix后,只有匹配该Prefix的Object才会复制到指标Bucket。-->
            <! --如果您须要将源Bucket中的所有Object复制到指标Bucket,则无需设置Prefix。
            <Prefix>prefix_1</Prefix>
            <Prefix>prefix_2</Prefix>
        </PrefixSet>
        <! --指定能够被复制到指标Bucket的操作。默认值为ALL,示意源Bucket的所有操作都会复制到指标Bucket。-->
        <Action>ALL</Action>
        <Destination>
            <! --指定数据要复制到的指标Bucket。-->
            <Bucket>destexamplebucket</Bucket>
            <! --指定指标Bucket所在的Region。-->
            <Location>oss-cn-beijing</Location>
            <! --指定数据复制时应用的数据传输链路。此处设置为oss_acc,示意应用了传输减速链路。-->
            <TransferType>oss_acc</TransferType>
        </Destination>
        <! --默认同步历史数据。此处设置为disabled,示意禁止同步历史数据。-->
        <HistoricalObjectReplication>disabled</HistoricalObjectReplication>
        <! --指定受权OSS进行数据复制的角色名称。如果指定应用SSE-KMS加密指标对象,则必须指定该元素。-->
        <SyncRole>aliyunramrole</SyncRole>
        <SourceSelectionCriteria>
          <SseKmsEncryptedObjects>
            <! --指定OSS是否复制通过SSE-KMS加密创立的对象。-->
            <Status>Enabled</Status>
          </SseKmsEncryptedObjects>
        </SourceSelectionCriteria>
        <EncryptionConfiguration>
            <! --指定SSE-KMS密钥ID。如果指定Status为Enabled,则必须指定该元素。-->
           <ReplicaKmsKeyID>c4d49f85-ee30-426b-a5ed-95e9139d****</ReplicaKmsKeyID>
       </EncryptionConfiguration>
     </Rule>
   </ReplicationConfiguration>`

    // 开启跨区域复制
    err = client.PutBucketReplication("srcexamplebucket",putXml)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}            

数据加密

OSS服务侧加密

ObjectOSS
ObjectOSSx-oss-server-side-encryptionOSS
package main

import (
    "fmt"
    "os"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 创立OSSClient实例
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 初始化加密规定,应用AES256算法
    config := oss.ServerEncryptionRule{
        SSEDefault: oss.SSEDefaultRule{SSEAlgorithm: "AES256"},
    }

    // 设置OSS服务侧加密
    err = client.SetBucketEncryption("examplebucket", config)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}

应用服务侧加密

ObjectOSSObjectOSS
package main

import (
    "bytes"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "os"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
    "github.com/aliyun/aliyun-oss-go-sdk/oss/crypto"
)

func main() {
    // 创立OSSClient实例。
    client, err := oss.New(
        "<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 创立一个主密钥的形容信息,创立后不容许批改。主密钥形容信息和主密钥一一对应。
    // 如果所有的Object都应用雷同的主密钥,主密钥形容信息能够为空,但后续不反对更换主密钥。
    // 如果主密钥形容信息为空,解密时无奈判断应用的是哪个主密钥。
    // 强烈建议为每个主密钥都配置主密钥形容信息(json字符串), 由客户端保留主密钥和形容信息之间的对应关系(服务端不保留两者之间的对应关系)。

    // 由主密钥形容信息(json字符串)转换的map。
    materialDesc := make(map[string]string)
    materialDesc["desc"] = "<your master encrypt key material describe information>"

    // 依据主密钥形容信息创立一个主密钥对象。
    masterRsaCipher, err := osscrypto.CreateMasterRsa(
        materialDesc, "<your rsa public key>", "<your rsa private key>",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 依据主密钥对象创立一个用于加密的接口, 应用aes ctr模式加密。
    contentProvider := osscrypto.CreateAesCtrCipher(masterRsaCipher)

    // 获取bucket。
    cryptoBucket, err := osscrypto.GetCryptoBucket(client, "<yourBucketName>", contentProvider)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 上传时时主动加密。
    err = cryptoBucket.PutObject(
        "<yourObjectName>", bytes.NewReader([]byte("yourObjectValueByteArray")),
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 下载时主动解密。
    body, err := cryptoBucket.GetObject("<yourObjectName>")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    defer func(b *io.ReadCloser) {
        err = (*b).Close()
        if err != nil {
            log.Println("Error:", err)
        }
    }(&body)

    data, err := ioutil.ReadAll(body)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    fmt.Println("data:", string(data))
}

版本控制

版本控制以回滚至任一历史版本的形式,为谬误笼罩谬误删除提供容错空间。

版本控制的一些限度

x-oss-forbid-overwrite

版本控制有三个状态:未开启开启暂停

package main

import (
    "fmt"
    "os"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 创立Client实例。
    client, err := oss.New(
        "<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>",
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 创立Bucket实例。
    err = client.CreateBucket("<yourBucketName>")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 开启版本控制。
    config := oss.VersioningConfig{Status: "Enabled"}
    err = client.SetBucketVersioning("<yourBucketName>", config)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 暂停版本控制。
    config.Status = "Suspended"
    err = client.SetBucketVersioning("<yourBucketName>", config)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}

防盗链

OSSrequest headerReferer
package main

import (
    "fmt"
    "os"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 创立Client实例。
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 初始化Referer白名单。反对通配符星号(*)和问号(?)。
    referers := []string{
        "http://www.aliyun.com",
        "http://www.???.aliyuncs.com",
        "http://www.*.com",
    }

    // 设置Referer白名单,并禁止空Referer
    // 留神:如果你配置了白名单但容许空Referer,终局会很生硬...
    err = client.SetBucketReferer("yourBucketName", referers, false)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 查问Bucket Referer
    res, e := client.GetBucketReferer("yourBucketName")
    if e != nil {
        fmt.Println("Error:", e)
        os.Exit(-1)
    }
    fmt.Println(res.RefererList, res.AllowEmptyReferer)
}

合规保留策略

合规保留策略容许用户以“不可删除、不可篡改”形式保留和应用数据,合乎美国证券交易委员会(SEC)和金融业监管局(FINRA)的合规要求。

package main

import (
    "fmt"
    "os"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 创立OSSClient实例。
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        handleError(err)
    }

    // 初始化WORM规定(锁定60天)。
    // 最短锁定1天,最长锁定70年。
    wormID, e := client.InitiateBucketWorm("examplebucket", 60)
    if e != nil {
        handleError(e)
    }

    /*
        初始化后的24小时内,WORM处于InProgress状态。
        在此期间,能够提交锁定,或者删除。
        若在此期间即未提交锁定也未删除,则WORM主动生效。
    */

    // 提交锁定
    err = client.CompleteBucketWorm("examplebucket", wormID)
    if err != nil {
        handleError(err)
    }

    // 或者删除
    /*
        err = client.AbortBucketWorm("examplebucket")
        if err != nil {
            handleError(err)
        }
    */

    // 通过Bucket查问WORM
    wormConfiguration, er := client.GetBucketWorm("examplebucket")
    if er != nil {
        handleError(er)
    }

    // WORM一旦提交锁定,在解锁日期前,WORM和Bucket内的所有Object均不反对删除。
    // 但能够缩短锁定期:
    err = client.ExtendBucketWorm(
        "examplebucket", 180, wormConfiguration.WormId,
    )
    if err != nil {
        handleError(err)
    }
}

func handleError(err error) {
    fmt.Println("Error:", err)
    os.Exit(-1)
}

日志

package main

import (
    "fmt"
    "os"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 创立OSSClient实例。
    client, err := oss.New(
        "yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret",
    )
    if err != nil {
        handleError(err)
    }

    // 开启
    // 将examplebucket的日志存入destbucket。
    err = client.SetBucketLogging("examplebucket", "destbucket", "log/", true)
    if err != nil {
        handleError(err)
    }

    // 查问
    res, e := client.GetBucketLogging("examplebucket")
    if e != nil {
        handleError(e)
    }
    fmt.Println(
        res.LoggingEnabled.TargetBucket, res.LoggingEnabled.TargetPrefix,
    )

    // 敞开
    err = client.DeleteBucketLogging("examplebucket")
    if err != nil {
        handleError(err)
    }
}

func handleError(err error) {
    fmt.Println("Error:", err)
    os.Exit(-1)
}

细节

避免意外笼罩

Headerx-oss-forbid-overwritetrue

防止批改门路

OSS
test1test2OSStest1/Objecttest2/ObjectOSS

性能与扩展性最佳实际

Object Key不要应用程序前缀!!!
Object Key不要应用程序前缀!!!
Object Key不要应用程序前缀!!!

阿里云 对象存储 OSS