全部产品
Search
文档中心

对象存储 OSS:开启请求者付费模式让请求者支付流量、请求次数、数据处理费用

更新时间:Feb 26, 2024

通常情况下,存储空间(Bucket)的拥有者需要支付Bucket产生的所有费用。然而,您可以为Bucket开启请求者付费模式,使通过身份验证的请求者支付访问Bucket内数据时产生的流量、请求次数、数据处理费用,而Bucket的拥有者仅支付存储等其他费用。当您希望共享数据,但又不希望支付因共享数据产生的额外费用时,您可以开启请求者付费模式。

使用场景

  • 共享大型数据集。例如某研究机构希望所有客户都能访问包含邮政编码目录、参考数据、地理空间信息或网络爬取等数据的共享数据集,同时希望下载数据产生的流量费用和请求次数费用需由请求者支付。

    配置步骤如下:

    1. 确保共享数据集所属Bucket的读写权限ACL为公共读。具体操作,请参见设置Bucket ACL

    2. 为该Bucket开启请求者付费模式。

  • 将生产数据交付给您的客户或合作伙伴。例如,某公司需要将生产数据交付给该公司的合作伙伴,下载数据产生的流量费用和请求次数费用需要由合作伙伴支付。

    配置步骤如下:

    1. 确保生产数据所属Bucket的读写权限ACL为私有。具体操作,请参见设置Bucket ACL

    2. 为该Bucket开启请求者付费模式。

    3. 通过Bucket Policy授权您的合作伙伴访问该Bucket内指定的生产数据。具体操作,请参见基于Bucket Policy实现跨账号访问OSS

    重要

    您需要将Bucket授权给合作伙伴的RAM用户,而不是将您账号下RAM用户的AccessKey提供给合作伙伴进行访问。原因是当合作伙伴通过您账号下的RAM用户访问时,请求者是您自身,请求费用仍需要您(请求者)来支付。

请求方式

  • 不允许匿名访问

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

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

  • 请求中需携带请求头x-oss-request-payer

    如果您在Bucket上启用了请求者付费模式,请求中必须携带x-oss-request-payer请求头,且取值为requester,以表明请求方已了解需要支付请求和数据下载费用。否则,请求方无法通过验证。

    • 对于POST、GET和HEAD请求,需在请求中包含x-oss-request-payer:requester信息。详情请参见签名版本4(推荐)

    • 对于签名URL,需在请求中包含x-oss-request-payer=requester信息。详情请参见签名版本4(推荐)

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

费用说明

请求者付费模式下,请求者会根据请求的内容支付请求费用、外网流出流量、CDN回源流出流量、图片处理、视频截帧、低频或归档数据取回、高级图片压缩费用中的一项或多项,Bucket拥有者仅支付存储费用、对象标签费用、传输加速费用等。关于各计费项的更多信息,请参见计费概述

如果出现以下情况,请求会失败,并返回HTTP 403错误,且由Bucket拥有者支付请求费用:

  • 请求者未在请求中(GET、HEAD或POST)包含请求头x-oss-request-payer

  • 请求身份验证失败。

  • 该请求是匿名请求。

操作步骤

使用OSS控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择Bucket 配置 > 请求者付费

  4. 请求者付费页面,打开请求者付费开关。

  5. 在弹出的对话框,单击确定

    说明

    如果您需要关闭请求者付费,您可以关闭请求者付费开关,然后单击确定

使用阿里云SDK

以下仅列举常见SDK的设置请求者付费模式的代码示例。关于其他SDK的设置请求者付费模式的代码示例,请参见SDK简介

import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;

public class Demo {
    public static void main(String[] args) throws Exception{
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
        try {
            // 设置请求者付费模式。
            Payer payer = Payer.Requester;
            ossClient.setBucketRequestPayment(bucketName, payer);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (Throwable ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\Core\OssException;

// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// Endpoint以杭州为例,其它Region请按实际情况填写。
$endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 填写Bucket名称,例如examplebucket。
$bucket= "examplebucket";

try {
    $config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
    );
    $ossClient = new OssClient($config);
    $ossClient->putBucketRequestPayment($bucket, "Requester");
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}

print(__FUNCTION__ . ": OK" . "\n");
const OSS = require('ali-oss')

const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET
});

async function setBucketRequestPayment(bucket, Payer) {
  try {
    // bucket填写需要设置请求者付费模式的存储空间名称。
    // Payer取值为Requester或BucketOwner。
    // Payer设置为Requester,表明该存储空间已开启请求者付费模式,由请求者支付读取存储空间(Bucket)内数据时产生的流量费用和请求费用。
    // Payer设置为BucketOwner,表明该存储空间不开启请求者付费模式(默认状态),即请求产生的费用由数据拥有者(BucketOwner)来支付。
    const result = await client.putBucketRequestPayment(bucket, Payer);
    console.log(result);
  } catch (e) {
    console.log(e);
  }
}

setBucketRequestPayment('bucketName', 'Requester')
# -*- coding: utf-8 -*-

import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import PAYER_BUCKETOWNER, PAYER_REQUESTER

# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# 填写Bucket名称,例如examplebucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')

# 设置请求者付费模式,默认的付费者为PAYER_BUCKETOWNER。
result = bucket.put_bucket_request_payment(PAYER_REQUESTER)

print("http respon status: ", result.status)
using Aliyun.OSS;
using Aliyun.OSS.Common;

// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写Bucket名称。
var bucketName = "examplebucket";

// 创建OSSClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
    // 设置请求者付费模式。
    var request = new SetBucketRequestPaymentRequest(bucketName, RequestPayer.Requester);
    client.SetBucketRequestPayment(request);
    Console.WriteLine("Set bucket:{0} RequestPayment succeeded ", bucketName);
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}
package main

import (
	"fmt"
	"os"

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

func main() {
	// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// 创建OSSClient实例。
	// yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
	client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
	if err != nil {
		fmt.Println("New Error:", err)
		os.Exit(-1)
	}

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

	// 设置请求者付费模式。
	err = client.SetBucketRequestPayment("<yourBucketName>", reqPayConf)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /*初始化OSS账号信息。*/
    
    /*yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /*填写Bucket名称,例如examplebucket。*/
    std::string BucketName = "examplebucket";

    /*初始化网络等资源。*/
    InitializeSdk();

    ClientConfiguration conf;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);

    /*设置请求者付费模式。*/
    SetBucketRequestPaymentRequest request(BucketName);
    request.setRequestPayer(RequestPayer::Requester);

    auto outcome = client.SetBucketRequestPayment(request);

    if (!outcome.isSuccess()) {
        /*异常处理。*/
        std::cout << "SetBucketRequestPayment fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /*释放网络等资源。*/
    ShutdownSdk();
    return 0;
}

使用命令行工具ossutil

关于使用ossutil设置请求者付费模式的具体操作, 请参见设置请求者付费模式

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见PutBucketRequestPayment