阿里云对象存储OSS的请求者付费模式是指由请求者支付读取存储空间(Bucket)内数据时产生的流量费用和请求费用,而Bucket拥有者仅支付存储费用。当您希望共享数据,但又不希望产生流量费用和请求费用时,您可以开启此功能。

请求方式说明

  • 不允许匿名访问

    如果您的Bucket启用了请求者付费模式,则不允许匿名访问该Bucket。请求方必须提供身份验证信息,以便OSS能够识别请求方,从而对请求方而非Bucket拥有者收取请求所产生的费用。

    当请求者是通过扮演阿里云RAM角色来请求数据时,该角色所属的账户将为此请求付费。

  • 申请方需携带x-oss-request-payer信息

    如果您的Bucket启用了请求者付费模式,请求方必须在PUT、POST、GET和HEAD等请求的Header信息中包含x-oss-request-payer:requester,以表明请求方知道请求和数据下载将产生费用。否则,请求方无法通过验证。

    数据拥有者访问该Bucket时,可以不携带x-oss-request-payer请求头。数据拥有者作为请求者访问该Bucket时,请求产生的费用由数据拥有者(也是请求者)来支付。

有关请求者付费模式的详情,请参见开发指南的请求者付费模式

设置请求者付费模式

以下代码用于设置请求者付费模式:

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)
  }

  // 初始化请求者付费模式。
  reqPayConf := oss.RequestPaymentConfiguration{
    Payer: "Requester",
  }

  // 设置bucket请求者付费模式。
  err = client.SetBucketRequestPayment("<yourBucketName>", reqPayConf)
  if err != nil {
    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 {
    fmt.Println("Error:", err)
    os.Exit(-1)
    }

  // 获取bucket请求者付费模式。
  ret, err := client.GetBucketRequestPayment("<yourBucketName>")
  if err != nil {
    fmt.Println("Error:", err)
    os.Exit(-1)
  }
  // 打印bucket请求者付费模式。
  fmt.Println("Bucket request payer:", ret.Payer)
}

第三方付费访问Object

第三方操作Object时需在http header中携带x-oss-request-payer:requester参数,否则会报错。

以下代码以PutObject、ListObjects、GetObject及DeleteObject为例,用于指定第三方付费访问Object。

其他用于指定第三方付费的Object读写操作接口设置方法类似。

以下代码用于设置第三方付费访问Object:

package main

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

func main() {
  // 创建OSSClient实例。
  // <Endpoint> 待访问bucket所在的域。
  // <yourAccessKeyId>  <yourAccessKeySecret> 外部访问者账户密码与密钥。
  payerClient, err := oss.New("<Endpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
  if err != nil {
    fmt.Println("New Error:", err)
    os.Exit(-1)
  }

  // 获取存储空间。
    // <bucketName> 该bucket拥有者开启了请求者付费模式,并授权给了外部访问者。
  payerBucket, err := payerClient.Bucket("<bucketName>")
  if err != nil {
    fmt.Println("Error:", err)
    os.Exit(-1)
  }

    // 当bucket拥有者开启付费模式时,必须设置oss.RequestPayer(oss.Requester)才可以访问授权的内容。
    // 当bucket拥有者没有开启付费模式时,外部访问者可以不用携带oss.RequestPayer(oss.Requester)参数。
    // bucket付费模式设置,可参考SetBucketRequestPayment。

  // 外部访问者上传文件,该外部访问者已取得bucket相应权限。
  key := "youObjectName"
  err = payerBucket.PutObject(key, strings.NewReader("<objectValue>"), oss.RequestPayer("requester"))
  if err != nil {
    fmt.Println("put Error:", err)
    os.Exit(-1)
  }

  // 列举bucket下的所有object,该外部访问者已取得bucket相应权限。
  // 作为外部授权的访问者,必须设置oss.RequestPayer(oss.Requester)才可以访问授权的内容。
  lor, err := payerBucket.ListObjects(oss.RequestPayer(oss.Requester))
  if err != nil {
    fmt.Println("Error:", err)
    os.Exit(-1)
  }
  // 打印object名字
  for _, l := range lor.Objects {
    fmt.Println("the Key name is :", l.Key)
  }

  // 外部访问者下载文件,该外部访问者已取得bucket相应权限。
  body, err := payerBucket.GetObject(key, oss.RequestPayer(oss.Requester))
  if err != nil {
    fmt.Println("Get Error:", err)
    os.Exit(-1)
  }
  // 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
  defer body.Close()

  // 读取并打印获取的内容。
  data, err := ioutil.ReadAll(body)
  if err != nil {
    fmt.Println("Error:", err)
    os.Exit(-1)
  }
  fmt.Println("data:", string(data))

  // 外部访问者删除文件,该外部访问者已取得bucket相应权限。
  err = payerBucket.DeleteObject(key, oss.RequestPayer(oss.Requester))
  if err != nil {
    fmt.Println("Error:", err)
    os.Exit(-1)
  }
}