全部產品
Search
文件中心

Object Storage Service:要求者付費

更新時間:Nov 19, 2025

對外共用大量資料時,可開啟儲存空間(Bucket)的要求者付費模式,將訪問資料產生的流量、請求等費用轉由資料要求者承擔,Bucket擁有者僅支付儲存費用等固定成本。為Bucket開啟要求者付費模式後,匿名訪問將被禁用,所有請求需經過身分識別驗證。

適用範圍

僅有地區屬性的Bucket支援開啟要求者付費模式。

工作原理

OSS 按以下邏輯處理請求:

  • 請求中攜帶 x-oss-request-payer頭,OSS 對要求者進行身分識別驗證,驗證通過後,流量和請求等費用由要求者承擔。

  • 請求中不攜帶 x-oss-request-payer 頭:

    • 要求者為 Bucket 擁有者:請求正常處理,所有費用由Bucket擁有者承擔。

    • 要求者非 Bucket 擁有者:請求被拒絕。

Bucket 擁有者配置要求者付費

步驟一:開啟要求者付費

  1. 登入OSS管理主控台

  2. 單擊Bucket 列表,然後單擊目標Bucket名稱。

  3. 在左側導覽列,選擇Bucket 配置 > 請求者付費

  4. 要求者付費頁面,開啟請求者付費開關。

  5. 在彈出的對話方塊,單擊確定

步驟二:為要求者授予存取權限

通過 Bucket Policy 為要求者授權訪問,否則要求者將無法訪問資料。

  1. Bucket列表,單擊目標Bucket名稱

  2. 在左側導覽列,選擇許可權控制 > Bucket 授權策略

  3. Bucket 授權策略頁面的按圖形策略添加頁簽,單擊新增授權

  4. 新增授權面板,填寫授權策略。其中,授權用戶選擇其他帳號,填寫要求者的帳號ID或RAM角色ARN(格式為 arn:sts::{RoleOwnerUid}:assumed-role/{RoleName}/{RoleSessionName})。

  5. 單擊確定

要求者發起付費請求

作為要求者,訪問已開啟要求者付費模式的Bucket時,必須在請求中聲明將承擔本次請求產生的費用。

控制台

  1. 登入OSS管理主控台

  2. 在左側導覽列,單擊我收藏的路徑右側的加號(+)。

  3. 添加收藏路徑對話方塊,按以下說明配置各項參數。

    參數

    說明

    添加方式

    選中從其他已授權bucket添加,將授權訪問的Bucket添加到收藏路徑。

    地區

    下拉選擇授權訪問的Bucket所在地區。

    Bucket

    添加授權訪問的Bucket名稱。

    請求者付費

    選中我已知曉並同意後,即聲明付費意願。可以正常訪問檔案路徑下的指定資源,訪問該Bucket產生的流量、請求次數等費用將由您支付。

SDK

以下代碼以PutObjectGetObjectDeleteObject為例,用於指定第三方付費訪問Object。其他用於指定第三方付費的Object讀寫操作介面設定方法類似。

第三方操作Object時需在HTTP Header中攜帶x-oss-request-payer:requester參數,否則會報錯。

Java

import com.aliyun.oss.ClientBuilderConfiguration;
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.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import java.io.ByteArrayInputStream;

public class Demo {
    public static void main(String[] args) throws Exception{
        // Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。關於其他Region對應的Endpoint資訊,請參見訪問網域名稱和資料中心。
        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";
        // 填寫Object完整路徑,例如exampledir/exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
        String objectName = "exampledir/exampleobject.txt";
        Payer payer = Payer.Requester;
        // 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為cn-hangzhou。
        String region = "cn-hangzhou";

        // 建立OSSClient執行個體。
        // 當OSSClient執行個體不再使用時,調用shutdown方法以釋放資源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();
        try {
            // PutObject介面指定付費者。
            String content = "hello";
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
            putObjectRequest.setRequestPayer(payer);
            ossClient.putObject(putObjectRequest);

            // GetObject介面指定付費者。
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectName);
            getObjectRequest.setRequestPayer(payer);
            OSSObject ossObject = ossClient.getObject(getObjectRequest);
            ossObject.close();

            // DeleteObject介面指定付費者。
            GenericRequest genericRequest = new GenericRequest(bucketName, objectName);
            genericRequest.setRequestPayer(payer);
            ossClient.deleteObject(genericRequest);
        } 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();
            }
        }
    }
}

Python

# -*- coding: utf-8 -*-

import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.headers import OSS_REQUEST_PAYER

# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

# 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"

# 填寫Endpoint對應的Region資訊,例如cn-hangzhou。注意,v4簽名下,必須填寫該參數
region = "cn-hangzhou"

# yourBucketName填寫儲存空間名稱。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)

# 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。
object_name = 'exampledir/exampleobject.txt'
headers = dict()
headers[OSS_REQUEST_PAYER] = "requester"

# 上傳檔案時指定header。
result = bucket.put_object(object_name, 'test-content', headers=headers)

# 下載檔案時指定header。
result = bucket.get_object(object_name, headers=headers)

# 刪除檔案時指定header。
result = bucket.delete_object(object_name, headers=headers);

Go

package main

import (
	"fmt"
	"io"
	"os"
	"strings"

	"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請按實際情況填寫。
	// yourRegion填寫Bucket所在地區,以華東1(杭州)為例,填寫為cn-hangzhou。其它Region請按實際情況填寫。
	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
	clientOptions = append(clientOptions, oss.Region("yourRegion"))
	// 設定簽名版本
	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
	payerClient, err := oss.New("yourEndpoint", "", "", clientOptions...)
	if err != nil {
		fmt.Println("New Error:", err)
		os.Exit(-1)
	}

	// 填寫Bucket名稱。
	payerBucket, err := payerClient.Bucket("examplebucket")
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	// 當Bucket擁有者開啟要求者付費模式後,外部存取者必須設定oss.RequestPayer(oss.Requester)參數才可以訪問授權的內容。
	// 當Bucket擁有者沒有開啟付費模式時,外部存取者可以不用攜帶oss.RequestPayer(oss.Requester)參數即可訪問授權的內容。

	// 上傳Object。
	// 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。
	key := "exampledir/exampleobject.txt"
	err = payerBucket.PutObject(key, strings.NewReader("objectValue"), oss.RequestPayer("requester"))
	if err != nil {
		fmt.Println("put Error:", err)
		os.Exit(-1)
	}

	// 列舉Bucket下的所有Object。
	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)
	}

	// 下載Object。
	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 := io.ReadAll(body)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	fmt.Println("data:", string(data))

	// 刪除Object。
	err = payerBucket.DeleteObject(key, oss.RequestPayer(oss.Requester))
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
}

Node.js

const OSS = require('ali-oss');
const bucket = 'bucket-name';
const payer = 'Requester';

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,
  authorizationV4: true,
  // yourBucketName填寫Bucket名稱。
  bucket: 'yourBucketName',

});

async function main() {
  await put();
  await get();
  await del();
}

async function put() {
  const result = await client.putBucketRequestPayment(bucket, payer);
  console.log('putBucketRequestPayment:', result);
  // PutObject介面指定付費者。
  const response = await client.put('fileName', path.normalize('D:\\localpath\\examplefile.txt'), {
    headers: {
      'x-oss-request-payer': 'requester'
    }
  });
  console.log('put:', response);
}

async function get() {
  const result = await client.putBucketRequestPayment(bucket, payer);
  console.log('putBucketRequestPayment:', result);
  // GetObject介面指定付費者。
  const response = await client.get('fileName', {
    headers: {
      'x-oss-request-payer': 'requester'
    }
  });
  console.log('get:', response);
}

async function del() {
  const result = await client.putBucketRequestPayment(bucket, payer);
  console.log('putBucketRequestPayment:', result);
  // DeleteObject介面指定付費者。
  const response = await client.delete('fileName', {
    headers: {
      'x-oss-request-payer': 'requester'
    }
  });
  console.log('delete:', response);
}

main();

C#

using System;
using System.IO;
using System.Text;
using Aliyun.OSS;
using Aliyun.OSS.Common;


namespace Samples
{
    public class Program
    {
        public static void Main(string[] args)
        {
            // yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
            var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數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名稱,例如examplebucket。
            var bucketName = "examplebucket";
            var objectName = "example.txt";
            var objectContent = "More than just cloud.";
            // 填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。
            const string region = "cn-hangzhou";
            // 建立ClientConfiguration執行個體,按照您的需要修改預設參數。
            var conf = new ClientConfiguration();
            // 設定v4簽名。
            conf.SignatureVersion = SignatureVersion.V4;

            // 建立OssClient執行個體。
            var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);

            try
            {
                byte[] binaryData = Encoding.ASCII.GetBytes(objectContent);
                MemoryStream requestContent = new MemoryStream(binaryData);
                // PutObject介面指定付費者。
                var putRequest = new PutObjectRequest(bucketName, objectName, requestContent);
                putRequest.RequestPayer = RequestPayer.Requester;
                var result = client.PutObject(putRequest);

                // GetObject介面指定付費者。
                var getRequest = new GetObjectRequest(bucketName, objectName);
                getRequest.RequestPayer = RequestPayer.Requester;
                var getResult = client.GetObject(getRequest);

                // DeleteObject介面指定付費者。
                var delRequest = new DeleteObjectRequest(bucketName, objectName);
                delRequest.RequestPayer = RequestPayer.Requester;
                client.DeleteObject(delRequest);
            }
            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);
            }
        }
    }
}

PHP

<?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";
// 填寫Object的完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。
$object = "exampledir/exampleobject.txt";

// 指定為要求者付費模式。
$options = array(
  OssClient::OSS_HEADERS => array(
  OssClient::OSS_REQUEST_PAYER => 'requester',
));

try {
    $config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
        "signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
        "region"=> "cn-hangzhou"
    );
    $ossClient = new OssClient($config);
    // PutObject介面指定付費者。
    $content = "hello";
    $ossClient->putObject($bucket, $object, $content, $options);

    // GetObject介面指定付費者。
    $ossClient->getObject($bucket, $object, $options);

    // DeleteObject介面指定付費者。
    $ossClient->deleteObject($bucket, $object, $options);
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}

print(__FUNCTION__ . ": OK" . "\n"); 

C++


#include <alibabacloud/oss/OssClient.h>
#include <fstream>
using namespace AlibabaCloud::OSS;
int main(void)
{
    /*初始化OSS帳號資訊。*/
    
    /*yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    
    / *yourRegion填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn - hangzhou。 * /
    std::string Region = "yourRegion";
    
    /*填寫要求者訪問的Bucket名稱,例如examplebucket。*/
    std::string BucketName = "examplebucket";    
    /*填寫要求者訪問的Object的完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。*/
    std::string ObjectName = "exampleobject.txt";
    /* 初始化網路等資源。*/
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已通過環境變數佈建要求者的OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);    

    /* 上傳檔案時佈建要求者付費模式。*/
    std::shared_ptr<std::iostream> content = std::make_shared<std::stringstream>();
    *content << "test cpp sdk";
    PutObjectRequest putrequest(BucketName, ObjectName, content);
    putrequest.setRequestPayer(RequestPayer::Requester);
    auto putoutcome = client.PutObject(putrequest);

    /* 下載檔案到本地記憶體時佈建要求者付費模式。*/
    GetObjectRequest getrequest(BucketName, ObjectName);
    getrequest.setRequestPayer(RequestPayer::Requester);
    auto getoutcome = client.GetObject(getrequest);

    /* 刪除檔案時佈建要求者付費模式。*/
    DeleteObjectRequest delrequest(BucketName, ObjectName);
    delrequest.setRequestPayer(RequestPayer::Requester);
    auto deloutcome = client.DeleteObject(delrequest);

    /* 釋放網路等資源。*/
    ShutdownSdk();
    return 0;
}

ossutil

使用命令列工具ossutil前,請先安裝ossutil

以使用 cp 命令下載對象為例,請指定 --request-payer=requester參數

ossutil cp oss://examplebucket/examplefile.txt  /localpath  --request-payer=requester

API

可直接發起REST API請求,需在要求標頭中加入 x-oss-request-payer: requester,並確保此要求標頭包含在簽名計算中,簽名的計算方法見在Header中包含簽名

GET /oss.jpg HTTP/1.1
Host: oss-example.oss-cn-hangzhou.aliyuncs.com
Date: Fri, 24 Feb 2012 06:38:30 GMT
Authorization: OSS4-HMAC-SHA256 Credential=LTAI********************/20250417/cn-hangzhou/oss/aliyun_v4_request,Signature=a7c3554c729d71929e0b84489addee6b2e8d5cb48595adfc51868c299c0c218e

應用於生產環境

  • RAM 角色訪問的計費歸屬:當要求者通過扮演阿里雲RAM角色來訪問資料時,該角色所屬的賬戶將為此請求付費。

    • 錯誤做法:讓要求者扮演Bucket 擁有者帳號下的 RAM 角色來擷取訪問資料的許可權。此情境下,所有請求是以 Bucket 擁有者的身份執行,產生的請求和流量費用仍將由 Bucket 擁有者支付,無法實現成本轉移。

    • 正確做法:通過Bucket Policy 直接為要求者授予訪問資料的許可權。

  • 預簽名 URL 陷阱

    • 錯誤做法:由 Bucket 擁有者使用身份憑證(AccessKey 或 STS 臨時憑證)產生預簽名 URL 並對外分享,此時請求是以Bucket 擁有者身份發起,相關費用由Bucket 擁有者承擔。

    • 正確做法:由請求方使用身份憑證(AccessKey 或 STS 臨時憑證)來產生預簽名 URL,並在產生時包含 x-oss-request-payer=requester 參數,簽名的計算方法見在URL中包含簽名。請求方將此 URL 對外分享使用時,費用由請求方承擔。

  • 相容性風險:開啟要求者付費會影響靜態網站託管依賴的匿名訪問機制,導致網站無法正常工作,建議將網站前端資源(HTML/CSS/JS)與需要要求者付費的資料分別部署在不同的Bucket中。

計費說明

Bucket開啟要求者付費前,所有費用均由Bucket擁有者支付。開啟要求者付費後,以下付費項由要求者的帳號支付,其餘計費項目還是由Bucket擁有者的帳號支付,完整計費項目參見OSS產品定價

費用

計費項目

流量費用

外網流出流量

CDN回源流出流量

請求費用

Put類型請求

Get類型請求

資料處理

低頻訪問資料取回容量

Archive Storage資料取回容量