This topic describes how to use a signed URL or temporary access credentials obtained from Security Token Service (STS) to grant a third-party user permissions to upload objects directly to Object Storage Service (OSS).

Prerequisites

A bucket is created. For more information, see Create buckets.

Background information

In a standard client/server system architecture, the server is responsible for receiving and processing requests from the client, and OSS is used as a backend storage service. In that case, the client sends the objects to upload to the application server. Then, the server forwards the objects to OSS. In this process, objects are transmitted twice: from the client to the server and from the server to OSS. In the case of bursts of access requests, the server must provide sufficient bandwidth resources for multiple clients to upload objects simultaneously. This presents a challenge to the architecture scalability.

Benefits

To resolve this issue, OSS provides authorized third-party upload. This way, each client can upload objects directly to OSS without transmitting them to the server. This reduces the cost of application servers and maximizes the OSS capability to process large amounts of data. Furthermore, you can focus on your business without worries about bandwidth and concurrency limits.

You have the option to use a signed URL or temporary access credentials to grant a third-party user permissions to upload objects directly to OSS.

Use temporary access credentials to authorize third-party users to upload objects to OSS

You can use Alibaba Cloud STS to authorize temporary access to OSS. STS is a web service that provides temporary access tokens for users. You can use STS to grant temporary access credentials that have a custom validity period and custom permissions to a third-party application or a RAM user that is managed by you. For more information about STS, see What is STS?

STS provides the following benefits:

  • You need to only generate an access token and send the access token to a third-party application. You do not need to expose your AccessKey pair to the third-party application. You can specify the access permissions and the validity period of the token.
  • The token automatically expires after the validity period. Therefore, you do not need to manually revoke the access permissions of a token.
Note You can call the AssumeRole operation or use STS SDKs for various programming languages to obtain temporary access credentials. For more information, see STS SDK overview. The temporary access credentials consist of a temporary AccessKey pair and a security token. The AccessKey pair consists of an AccessKey ID and an AccessKey secret. The unit of the validity period of temporary access credentials is seconds. The minimum validity period of temporary access credentials is 900 seconds. The maximum validity period of temporary access credentials is the maximum session duration specified for the current role. For more information, see Specify the maximum session duration for a RAM role.

Use OSS SDKs

The following sample code provides examples on how to use temporary access credentials to authorize a third-party user to upload objects to OSS by using OSS SDKs for common programming languages. For more information about how to perform this operation by using OSS SDKs for other programming languages, see Overview.

import com.aliyun.oss.*;
import com.aliyun.oss.model.PutObjectRequest;
import java.io.File;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Specify the temporary AccessKey pair obtained from STS. 
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // Specify the security token obtained from STS. 
        String securityToken = "yourSecurityToken";
        // Specify the name of the bucket. Example: examplebucket. 
        //String bucketName = "examplebucket";
        // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object. 
        //String objectName = "exampleobject.txt";
        //String pathName = "D:\\localpath\\examplefile.txt";

        // Use the temporary access credentials obtained from STS to create an OSSClient instance. 
        // Create an OSSClient instance. 
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);

        try {
            // Perform operations on OSS resources, such as uploading or downloading objects. 
            // Upload an object. In this example, a local file is uploaded to OSS. 
            // Specify the full path of the local file that you want to upload. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs. 
            //PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(pathName));
            //ossClient.putObject(putObjectRequest);
        } 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 (ClientException 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 {
            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\OssClient;
use OSS\Core\OssException;

// Specify the temporary AccessKey pair obtained from STS. 
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// Specify the security token obtained from STS. 
$securityToken = "yourSecurityToken";
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
$endpoint = "yourEndpoint";
// Specify the name of the bucket. 
$bucket= "examplebucket";
// Specify the full path of the object. Do not include the bucket name in the full path. 
$object = "exampleobject.txt";
// Specify the string that you want to upload. 
$content = "Hello OSS";

try {
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken);
    // Upload the object by using the temporary access credentials obtained from STS. 
    $ossClient->putObject($bucket, $object, $content);
} catch (OssException $e) {
    print $e->getMessage();
}           
# -*- coding: utf-8 -*-
from aliyunsdkcore.request import CommonRequest
from aliyunsdkcore import client
import json
import oss2

# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
endpoint = 'https://oss-cn-hangzhou.aliyuncs.com'
# The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
access_key_id = 'yourAccessKeyId'
access_key_secret = 'yourAccessKeySecret'
# Specify the name of the bucket. Example: examplebucket. 
bucket_name = 'examplebucket'
# Specify the full path of the object. Do not include the bucket name in the full path of the object. Example: exampledir/exampleobject.txt. 
object_name = 'exampledir/exampleobject.txt'
# To obtain the Alibaba Cloud Resource Name (ARN) of the RAM role, log on to the RAM console. In the left-side navigation pane, choose Identities > Roles. On the Roles page, find the RAM role and click the role name. In the Basic Information section of the role details page, you can view and copy the ARN of the RAM role. 
# Specify the ARN of the RAM role. Format: acs:ram::$accountID:role/$roleName. 
# Set $accountID to the ID of your Alibaba Cloud account. To view the ID of your Alibaba Cloud account, perform the following steps: Log on to the OSS console, and move the pointer over the profile picture in the upper-right corner or click Basic Information. 
# Set $roleName to the name of the RAM role. To view the name of the RAM role, perform the following steps: Log on to the RAM console. In the left-side navigation pane, choose Identities > Roles. On the Roles page, view the name of the RAM role. 
role_arn = 'acs:ram::17464958********:role/ossststest'

# Create a RAM policy. 
# The RAM policy specifies that the user has permissions to call the PutObject operation only on objects in the examplebucket bucket. 
policy_text = '{"Version": "1", "Statement": [{"Action": ["oss:PutObject"], "Effect": "Allow", "Resource": ["acs:oss:*:*:examplebucket/*"]}]}'

clt = client.AcsClient(access_key_id, access_key_secret, 'cn-hangzhou')

request = CommonRequest(product="Sts", version='2015-04-01', action_name='AssumeRole')
request.set_method('POST')
request.set_protocol_type('https')
request.add_query_param('RoleArn', role_arn)
request.add_query_param('RoleSessionName', 'SessionTest')
# If the RAM policy is left empty, the user has all permissions of the RAM role. If you have specific requirements on the permissions, refer to the preceding configurations of policy_text. 
request.add_query_param('Policy', policy_text)
request.set_accept_format('JSON')

body = clt.do_action_with_exception(request)

# Use the AccessKey pair of the RAM user to apply for temporary access credentials from STS. 
token = json.loads(oss2.to_unicode(body))

# Initialize the StsAuth instance based on the authentication information in the temporary access credentials. 
auth = oss2.StsAuth(token['Credentials']['AccessKeyId'],
                    token['Credentials']['AccessKeySecret'],
                    token['Credentials']['SecurityToken'])

# Initialize the bucket based on the StsAuth instance. 
bucket = oss2.Bucket(auth, endpoint, bucket_name)

# Upload the object. 
content = 'testabc'
result = bucket.put_object(object_name, content)
print('http response status: ', result.status)
                    
package main


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

func main() {    
    // Specify the security token obtained from STS. 
    securitytoken := "yourSecurityToken"
    // Specify the temporary AccessKey pair obtained from STS. 
    // Use the temporary access credentials obtained from STS to create an OSSClient instance. 
    // Create an OSSClient instance. 
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret", oss.SecurityToken(securitytoken))
    if err != nil {
        fmt.Println("Error:", err)
    os.Exit(-1)    

    }
    // Specify the name of the bucket. Example: examplebucket. 
    bucketName := "examplebucket"
    // Specify the full path of the object. Do not include the bucket name in the full path of the object. Example: exampledir/exampleobject.txt. 
    objectName := "exampledir/exampleobject.txt"
    // Specify the full path of the local file. Example: D:\\localpath\\examplefile.txt. 
    filepath := "D:\\localpath\\examplefile.txt"
    bucket,err := client.Bucket(bucketName)
    // Upload the object by using the temporary access credentials obtained from STS. 
    err = bucket.PutObjectFromFile(objectName,filepath)
    fmt.Println(err)
}                    

Use a signed URL to authorize third-party users to upload objects to OSS

Important A validity period must be specified for temporary access credentials and a signed URL. When you use temporary access credentials to generate a signed URL that is used to perform operations, such as object upload and download, the minimum validity period takes precedence. For example, you can set the validity period of the temporary access credentials that are provided by STS to 1,200 seconds and the validity period of the signed URL generated by using the credentials to 3,600 seconds. In this case, you cannot use the signed URL to upload objects after the temporary access credentials expire, even if the signed URL is within the validity period.

You can generate a signed URL and provide the URL to a third-party user for temporary access. When you generate a signed URL, you can specify the validity period of the URL to limit the access period of the authorized third-party user.

You can add signature information to a URL and provide the URL to a third-party user for authorized access. For more information, see Add signatures to URLs.

Use OSS SDKs

The following sample code provides examples on how to use a signed URL to authorize a third-party user to upload objects to OSS by using OSS SDKs for common programming languages. For more information about how to perform this operation by using OSS SDKs for other programming languages, see Overview.

import com.aliyun.oss.*;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.StorageClass;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.*;
import java.net.URL;
import java.util.*;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Specify the temporary AccessKey pair obtained from STS. The AccessKey pair consists of an AccessKey ID and an AccessKey secret. 
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // Specify the security token obtained from STS. 
        String securityToken = "yourSecurityToken";
        // Specify the name of the bucket. Example: examplebucket. 
        String bucketName = "examplebucket";
        // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path. 
        String objectName = "exampleobject.txt";
        // Specify the full path of the local file that you want to upload. By default, if you do not specify the full path, the local file is uploaded from the path of the project to which the sample program belongs. 
        String pathName = "D:\\localpath\\examplefile.txt";

        // Use the temporary access credentials obtained from STS to create an OSSClient instance. 
        // Use the temporary access credentials obtained from STS to create an OSSClient instance. 
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);
        // Do not use the temporary access credentials obtained from STS to create an OSSClient instance. 
        // OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // Specify request headers. 
        Map<String, String> headers = new HashMap<String, String>();
        /*// Specify the storage class of the object. 
        headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
        // Specify the content type. 
        headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/

        // Specify user metadata. 
        Map<String, String> userMetadata = new HashMap<String, String>();
        /*userMetadata.put("key1","value1");
        userMetadata.put("key2","value2");*/

        URL signedUrl = null;
        try {
            // Specify the validity period of the signed URL. Unit: milliseconds. 
            Date expiration = new Date(new Date().getTime() + 3600 * 1000);

            // Generate the signed URL. 
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
            // Specify the expiration time of the signed URL. 
            request.setExpiration(expiration);

            // Add the headers to the request. 
            request.setHeaders(headers);
            // Specify user metadata. 
            request.setUserMetadata(userMetadata);

            // Generate a signed URL that allows HTTP PUT requests. 
            signedUrl = ossClient.generatePresignedUrl(request);
            // Display the signed URL. 
            System.out.println("signed url for putObject: " + signedUrl);

        } 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 (ClientException 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());
        }

        // Use the signed URL to upload the object. In this example, HttpClients is used. 
        putObjectWithHttp(signedUrl, pathName, headers, userMetadata);
    }

    public static void putObjectWithHttp(URL signedUrl, String pathName, Map<String, String> headers, Map<String, String> userMetadata) throws IOException {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            HttpPut put = new HttpPut(signedUrl.toString());
            HttpEntity entity = new FileEntity(new File(pathName));
            put.setEntity(entity);
            // If you configure header parameters such as the user metadata and storage class when a signed URL is generated, these parameters must be sent to the server when the signed URL is used to upload the object. If parameters for the signature are inconsistent with those sent to the server, a signature error is reported. 
            for(Map.Entry header: headers.entrySet()){
                put.addHeader(header.getKey().toString(),header.getValue().toString());
            }
            for(Map.Entry meta: userMetadata.entrySet()){
                // If userMeta is used, the x-oss-meta- prefix is added to userMeta. When you use other methods to generate a signed URL for object upload, the x-oss-meta- prefix is also added to userMata. 
                put.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString());
            }

            httpClient = HttpClients.createDefault();

            response = httpClient.execute(put);

            System.out.println("Upload status code:"+response.getStatusLine().getStatusCode());
            if(response.getStatusLine().getStatusCode() == 200){
                System.out.println("Upload successfully using the network library");
            }
            System.out.println(response.toString());
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            response.close();
            httpClient.close();
        }
    }
}       
<?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\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;

// Specify the temporary AccessKey pair obtained from STS. 
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// Specify the security token obtained from STS. 
$securityToken = "yourSecurityToken";
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
$endpoint = "yourEndpoint";
// Specify the name of the bucket. 
$bucket= "examplebucket";
// Specify the full path of the object. Do not include the bucket name in the full path of the object. 
$object = "exampleobject.txt";
// Set the validity period of the signed URL to 3600. Unit: seconds. 
$timeout = 3600;
try {
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken);

    // Generate a signed URL. 
    $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT");
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
print(__FUNCTION__ . ": signedUrl: " . $signedUrl . "\n");

// Use the signed URL to upload the object. 
// Specify the string that you want to upload. 
$content = "Hello OSS";
$request = new RequestCore($signedUrl);
// Set the method used to access the signed URL to PUT. 
$request->set_method('PUT');
$request->add_header('Content-Type', 'application/txt');
$request->add_header('Content-Length', strlen($content));
$request->set_body($content);
$request->send_request();
$res = new ResponseCore($request->get_response_header(),
    $request->get_response_body(), $request->get_response_code());
if ($res->isOK()) {
    print(__FUNCTION__ . ": OK" . "\n");
} else {
    print(__FUNCTION__ . ": FAILED" . "\n");
};                 
# -*- coding: utf-8 -*-
import oss2

# The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
auth = oss2.Auth('yourAccessKeyId', 'yourAccessKeySecret')
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
# Specify the name of the bucket. Example: examplebucket. 
bucket = oss2.Bucket(auth, 'yourEndpoint', 'examplebucket')
# Specify the full path of the object. Example: exampledir/exampleobject.txt. Do not include the bucket name in the full path of the object. 
object_name = 'exampledir/exampleobject.txt'

# Generate a signed URL that is used to upload the object. Set the validity period of the signed URL to 60. Unit: seconds. 
# By default, OSS identifies the forward slashes (/) in the full path of an object as escape characters when the signed URL is generated. Therefore, you cannot use the signed URL to upload the object. 
# Set the slash_safe parameter to True. This way, OSS does not identify the forward slashes (/) in the full path of the object as escape characters. Then, you can use the generated signed URL to upload the object. 
url = bucket.sign_url('PUT', object_name, 60, slash_safe=True) 
print('the signed URL:', url)

# Use the signed URL to upload a local file. 
# Specify the full path of the local file. Example: D:\\localpath\\examplefile.txt. 
# If you specify only the name of the local file, such as example-new.jpg, but do not specify the local path, the local file is uploaded from the local path of the project to which the sample program belongs. 
result = bucket.put_object_with_url_from_file(url, 'D:\\localpath\\examplefile.txt')
print(result.status)         
package main

import (
    "fmt"
    "os"
    "strings"

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

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

func main() {
    // You can use the temporary AccessKey pair and security token obtained from STS to create an OSSClient instance. 
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret", oss.SecurityToken("yourSecurityToken"))
    if err != nil {
        HandleError(err)
    }
    // Specify the name of the bucket. Example: examplebucket. 
    bucketName := "examplebucket"
    // Specify the full path of the object. Example: exampledir/exampleobject.txt. Do not include the bucket name in the full path of the object. 
    objectName := "exampledir/exampleobject.txt"
    // Specify the full path of the local file. Example: D:\\localpath\\examplefile.txt. localpath indicates the local path of the examplefile.txt file. 
    localFilename := "D:\\localpath\\examplefile.txt"

    // Query the bucket. 
    bucket, err := client.Bucket(bucketName)
    if err != nil {
        HandleError(err)
    }

    // Upload the object by using the signed URL. 
    signedURL, err := bucket.SignURL(objectName, oss.HTTPPut, 60)
    if err != nil {
        HandleError(err)
    }

    var val = "Go with Alibaba Cloud"
    err = bucket.PutObjectWithURL(signedURL, strings.NewReader(val))
    if err != nil {
        HandleError(err)
    }

    // Upload the object by using the signed URL with optional parameters configured. Make sure that the value of the ContentType parameter in the URL is the same as the value of the ContentType parameter specified in the request. 
    options := []oss.Option{
        oss.Meta("myprop", "mypropval"),
        oss.ContentType("text/plain"),
    }

    signedURL, err = bucket.SignURL(objectName, oss.HTTPPut, 60, options...)
    if err != nil {
        HandleError(err)
    }

    err = bucket.PutObjectFromFileWithURL(signedURL, localFilename, options...)
    if err != nil {
        HandleError(err)
    }
}
                    
using Aliyun.OSS;
using Aliyun.OSS.Common;
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the bucket. Example: examplebucket. 
var bucketName = "examplebucket";
// Specify the full path of the object. Do not include the bucket name in the full path of the object. Example: exampledir/exampleobject.txt. 
var objectName = "exampledir/exampleobject.txt";
var objectContent = "More than just cloud.";
// Create an OSSClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
    // Generate a signed URL. 
    var generatePresignedUriRequest = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Put)
    {
        // Specify the content type. 
        ContentType = "text/html", 
        // Specify the validity period of the signed URL. Default value: 3600. Unit: seconds. 
        Expiration = DateTime.Now.AddHours(1),
    };
    var signedUrl = client.GeneratePresignedUri(generatePresignedUriRequest);
}
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);
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* Initialize the information about the account that is used to access OSS. */
    /* The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. */
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    /* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
    std::string Endpoint = "yourEndpoint";
    /* Specify the name of the bucket. Example: examplebucket. */
    std::string BucketName = "examplebucket";
    /* Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. */   
    std::string PutobjectUrlName = "exampledir/exampleobject.txt";

     /* Initialize resources, such as network resources. */
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);

    /* Specify the validity period of the signed URL. */
    std::time_t t = std::time(nullptr) + 1200;
    /* Generate the signed URL. */
    auto genOutcome = client.GeneratePresignedUrl(BucketName, PutobjectUrlName, t, Http::Put);
    if (genOutcome.isSuccess()) {
        std::cout << "GeneratePresignedUrl success, Gen url:" << genOutcome.result().c_str() << std::endl;
    }
    else {
        /* Handle exceptions. */
        std::cout << "GeneratePresignedUrl fail" <<
        ",code:" << genOutcome.error().Code() <<
        ",message:" << genOutcome.error().Message() <<
        ",requestId:" << genOutcome.error().RequestId() << std::endl;
        return -1;
    }

    /* Release resources, such as network resources. */
    ShutdownSdk();
    return 0;
}