The PostObject operation lets you upload files directly from a web client to Object Storage Service (OSS). It uses a server-generated signature for security and lets you configure a policy to restrict uploads based on your business requirements.
Solution overview
To implement direct upload with server-side signing, follow these three steps:
Using a temporary access credential prevents exposing your server's long-term key, enhancing file upload security.
-
Configure OSS: Create a bucket in the console to store user files. Then, configure Cross-Origin Resource Sharing (CORS) rules for the bucket to allow cross-origin requests from the web client.
-
Configure the server: Call the Security Token Service (STS) to obtain a temporary access credential. Then, use this credential and a server-side upload policy to generate a signature. This policy includes parameters such as the bucket name, directory path, and expiration time. This signature authorizes a user to upload files for a specified period.
-
Configure the web client: Construct an HTML form request and use the signature to upload the file to OSS.
Sample projects
-
For the Java sample project, see server-signed-direct-upload-java.zip.
-
For the Python sample project, see server-signed-direct-upload-python.zip.
-
For the Node.js sample project, see server-signed-direct-upload-nodejs.zip.
-
For the Go sample project, see server-signed-direct-upload-go.zip.
-
For the PHP sample project, see server-signed-direct-upload-php.zip.
Steps
Step 1: Configure OSS
Create a bucket
Create an OSS bucket to store files uploaded directly from a web browser.
-
Log in to the OSS console.
-
In the left-side navigation pane, click Buckets, then click Create Bucket.
-
In the Create Bucket panel, select Quick Create and configure the following parameters:
Parameter
Sample value
Bucket Name
web-direct-upload
Region
China (Hangzhou)
-
Click Create.
Configure a CORS rule
Configure a CORS rule for your OSS bucket.
-
On the Buckets page, click the target bucket.
-
On the CORS page, click Create Rule.
-
In the Create Rule panel, set the following parameters.
Parameter
Sample value
Origin
*
Allowed Methods
POST, PUT, GET
Allowed Headers
*
-
Click OK.
Step 2: Configure server
For a production deployment, if you already have a server, skip the preparations and go directly to 1. Configure user permissions.
Create an ECS instance
Step 1: Create an ECS instance
Go to the Custom Launch page and select the basic resources needed to create an ECS instance.
-
Select a region and billing method
-
Select a billing method based on your business requirements. This tutorial uses the pay-as-you-go mode for its flexibility.
-
Generally, choosing a region closer to your users results in lower network latency and faster access. This tutorial uses China (Hangzhou) as an example.
For Billing Method, select pay-as-you-go (post-paid and on-demand). Pay-as-you-go instances do not support ICP filing. After an instance is created, its region cannot be changed. Instances in different regions cannot communicate over an internal network.
-
-
Create a Virtual Private Cloud (VPC) and a vSwitch
When you create a VPC, select the same region as the ECS instance and plan the CIDR blocks based on your business requirements. This tutorial uses the creation of a VPC and a vSwitch in the China (Hangzhou) region as an example. After creating the VPC and vSwitch, return to the ECS purchase page, refresh it, and select them.
NoteYou can create a vSwitch when you create a VPC.

On the Create VPC page, set Name to ProjectA-VPC, select Manually Specify IPv4 CIDR Block for IPv4 CIDR Block and enter
192.168.0.0/16, and select Do Not Assign for IPv6 CIDR Block.Example vSwitch configuration: Set Name to ProjectA-vSwitch, select Hangzhou Zone H for Zone, set the IPv4 CIDR Block to
192.168.10.0/24, and then click OK.
-
Select an instance type and image
Select an instance type and image. The image determines the operating system and version installed on the instance. This tutorial uses the
ecs.e-c1m1.largeinstance type, which is cost-effective and meets the testing requirements. The image is theAlibaba Cloud Linux 3.2104 LTS 64-bitpublic image.
-
Configure storage
For the simple web system in this tutorial, a system disk is sufficient for the operating system, so a data disk is not required.
For the system disk, select ESSD, set Performance Level to PL0 and Capacity to 40 GiB, select Release with Instance, and do not add a data disk.
-
Assign a public IP address
For simplicity, this tutorial assigns a public IP address directly to the instance. Alternatively, you can associate an Elastic IP Address (EIP) with the instance after creating it. For more information, see Associate an EIP with a cloud resource.
Note-
If a public IP address is not assigned, you cannot use SSH or Remote Desktop Protocol (RDP) to directly access the instance from the internet, nor can you verify the deployment of the web service on the instance.
-
This tutorial uses the pay-by-traffic bandwidth billing method. This method charges you only for the public traffic you consume. For more information, see Public bandwidth billing.
Set Peak bandwidth to 5 Mbps.
-
-
Create a security group
Create a security group for the instance. A security group is a virtual firewall that controls inbound and outbound traffic for an ECS instance. When you create the security group, allow traffic on the following ports so you can access the ECS instance later.
Port range: SSH (22), RDP (3389), HTTP (80), and HTTPS (443).
Note-
The ports selected for Port range are required for the applications running on the ECS instance.
-
By default, the security group created here includes a rule that sets the source to 0.0.0.0/0. This allows access from any IP address to the specified ports. If you know the IP addresses of the requesting clients, we recommend that you later restrict the source to a specific IP range. For more information, see Modify a security group rule.
In the Security group type section, select Basic security group.
-
-
Create a key pair
-
A key pair provides secure logon credentials. After creating a key pair, you must download its private key, which is required to connect to an ECS instance. Then, return to the ECS purchase page, refresh it, and select the key pair.
-
The
rootuser has the highest privileges in the operating system, and usingrootas the login name may cause security risks. We recommend that you useecs-useras the login name.NoteAfter you create a key pair, the private key is automatically downloaded. Save the
.pemprivate key file from your browser's download history.In the Logon Credential section, select the Key pair tab, click Create key pair. Then, select the newly created key pair (for example,
ecs-test) from the Key pair drop-down list.
-
-
Create and view the ECS instance
After you select the required resources for the ECS instance, click Create order. In the success dialog box, click Management console to view the new instance. Save the following information for later use:
-
Instance ID: Used to find the instance in the instance list.
-
Region: Used to find the instance in the instance list.
-
Public IP address: Used to verify the deployment of the web service.
-
Step 2: Connect to the ECS instance
-
On the Instances page of the ECS console, find your instance using its region and ID, and then in the Actions column, click Connect.
-
In the Remote connection dialog box, click Sign in now next to Workbench.
-
In the Log on to instance dialog box, select Terminal connection for Connection method and SSH key authentication for Authentication method. Then, enter or upload your private key file, and click Log on to connect as the
ecs-useruser. -
Note
The private key file (
.pem) is automatically downloaded to your device when you create the key pair. Check your browser's download history to find the file. -
When the following output is displayed, you have successfully logged on to the ECS instance.
Welcome to Alibaba Cloud Elastic Compute Service ! Last login: Sun Sep 29 15:35:22 2024 from xxx [ecs-user@iz*** ~]$
User permissions
To prevent OSS uploads from failing after deployment due to insufficient permissions, create a RAM user and configure the required permissions.
Step 1: Create a RAM user
Create a RAM user and obtain its AccessKey pair to serve as the long-term credentials for your application server.
-
Log on to the RAM console with your Alibaba Cloud account or as a RAM administrator.
-
In the left-side navigation pane, choose Identities > Users.
-
Click Create User.
-
Enter a Logon Name and a Display Name.
-
In the Access Mode section, select Programmatic access, and then click OK.
The AccessKey secret is displayed only upon creation and cannot be retrieved later. Store it securely.
-
In the Actions column, click Copy to save the AccessKey pair (AccessKey ID and AccessKey secret).
Step 2: Grant AssumeRole permission
After you create the RAM user, grant it permission to call the STS AssumeRole operation. This allows the user to obtain temporary credentials by assuming a RAM role.
-
In the left-side navigation pane, choose Identities > Users.
-
On the Users page, find the target RAM user, and then click Add Permissions in the Actions column.
-
On the Grant Permission page, select the AliyunSTSAssumeRoleAccess System Policy.
NoteThe AliyunSTSAssumeRoleAccess policy grants permission to call the
AssumeRoleoperation. It does not grant permissions for subsequent operations that use the temporary credentials, such as OSS requests. -
Click OK.
Step 3: Create a RAM role
Create a RAM role for the current Alibaba Cloud account and obtain its Alibaba Cloud Resource Name (ARN). The RAM user will assume this role.
-
In the left-side navigation pane, choose Identities > Roles.
-
Click Create Role. For Principal Type, select Alibaba Cloud Account.
-
Select the current Alibaba Cloud account and click OK.
-
Enter a role name and click OK.
-
On the RAM role details page, click Copy to save the ARN of the role.
Step 4: Create a file upload policy
Following the principle of least privilege, create a Custom Policy for the RAM role that restricts uploads to a specific OSS bucket.
-
In the left-side navigation pane, choose Permissions > Policies.
-
Click Create Policy.
-
On the Create Policy page, click JSON Editor and replace
<Bucket name>in the script with the bucket nameweb-direct-uploadthat you created in the Preparations section.{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "oss:PutObject", "Resource": "acs:oss:*:*:<BucketName>/*" } ] } -
After you configure the policy, click OK.
-
In the Create Policy dialog box, enter a Policy Name and click OK.
Step 5: Grant permissions to the RAM role
Grant the Custom Policy you created to the RAM role. This gives the assumed role the required permissions.
-
In the left-side navigation pane, choose Identities > Roles.
-
On the Roles page, find the target RAM role, and then click Add Permissions in the Actions column.
-
On the Grant Permission page, select Custom Policy, and then choose the policy you created.
-
Click OK.
Server-side signature
We recommend configuring sensitive information, such as AccessKey ID, AccessKey Secret, and Role ARN, as environment variables. This practice avoids hardcoding them in your code and reduces the risk of credential leaks.
Follow these steps to set the environment variables.
Linux
-
From the command line, run the following commands to append the environment variable settings to the
~/.bashrcfile.echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.bashrc echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.bashrc echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.bashrc -
Run the following command to apply the changes.
source ~/.bashrc -
Run the following commands to verify that the environment variables are set.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
macOS
-
In the terminal, run the following command to check your default shell.
echo $SHELL -
Follow the instructions for your default shell.
Zsh
-
Run the following commands to append the environment variable settings to the
~/.zshrcfile.echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.zshrc echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.zshrc echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.zshrc -
Run the following command to apply the changes.
source ~/.zshrc -
Run the following commands to verify that the environment variables are set.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
Bash
-
Run the following commands to append the environment variable settings to the
~/.bash_profilefile.echo "export OSS_ACCESS_KEY_ID='your-access-key-id'" >> ~/.bash_profile echo "export OSS_ACCESS_KEY_SECRET='your-access-key-secret'" >> ~/.bash_profile echo "export OSS_STS_ROLE_ARN='your-role-arn'" >> ~/.bash_profile -
Run the following command to apply the changes.
source ~/.bash_profile -
Run the following commands to verify that the environment variables are set.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
-
Windows
-
Run the following commands in Command Prompt (CMD).
setx OSS_ACCESS_KEY_ID "your-access-key-id" setx OSS_ACCESS_KEY_SECRET "your-access-key-secret" setx OSS_STS_ROLE_ARN "your-role-arn" -
Open a new CMD window.
-
In the new CMD window, run the following commands to verify that the environment variables are set.
echo %OSS_ACCESS_KEY_ID% echo %OSS_ACCESS_KEY_SECRET% echo %OSS_STS_ROLE_ARN%
Use the following sample code to calculate a POST signature on the server with Signature Version 4 (recommended). For more information about configuring the policy form field, see policy form field.
Java
Add the following dependencies to your Maven project.
<!-- https://mvnrepository.com/artifact/com.aliyun/credentials-java -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>sts20150401</artifactId>
<version>1.1.6</version>
</dependency>
The following sample code shows how to obtain a temporary access credential and calculate a POST signature on the server:
package com.aliyun.oss.web;
import com.aliyun.sts20150401.models.AssumeRoleResponse;
import com.aliyun.sts20150401.models.AssumeRoleResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Controller
public class WebController {
// Basic OSS information. Replace with your actual bucket name, region ID, and host.
String bucket = "examplebucket";
String region = "cn-hangzhou";
String host = "http://examplebucket.oss-cn-hangzhou.aliyuncs.com";
// Set the upload callback URL, which is the address of your callback server. This must be a public URL. OSS uses this URL to send object upload information to your application server.
// The prefix (directory) for objects to be uploaded to OSS.
String upload_dir = "dir";
// The expiration time in seconds.
Long expire_time = 3600L;
/**
* Generates an expiration time based on a specified duration in seconds.
* @param seconds The duration in seconds.
* @return An ISO 8601 time string, such as "2014-12-01T12:00:00.000Z".
*/
public static String generateExpiration(long seconds) {
// Get the current timestamp in seconds.
long now = Instant.now().getEpochSecond();
// Calculate the expiration timestamp.
long expirationTime = now + seconds;
// Convert the timestamp to an Instant object and format it to ISO 8601.
Instant instant = Instant.ofEpochSecond(expirationTime);
// Define the time zone as UTC.
ZoneId zone = ZoneOffset.UTC;
// Convert the Instant to a ZonedDateTime.
ZonedDateTime zonedDateTime = instant.atZone(zone);
// Define the date-time format, for example, 2023-12-03T13:00:00.000Z.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
// Format the date and time.
String formattedDate = zonedDateTime.format(formatter);
// Return the result.
return formattedDate;
}
// Initialize the STS client.
public static com.aliyun.sts20150401.Client createStsClient() throws Exception {
// Hardcoding an AccessKey pair is a security risk and not recommended. This code is for reference only.
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// Required. Make sure that the OSS_ACCESS_KEY_ID environment variable is set in your code's runtime environment.
.setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID"))
// Required. Make sure that the OSS_ACCESS_KEY_SECRET environment variable is set in your code's runtime environment.
.setAccessKeySecret(System.getenv("OSS_ACCESS_KEY_SECRET"));
// For more information about endpoints, see https://api.aliyun.com/product/Sts.
config.endpoint = "sts.cn-hangzhou.aliyuncs.com";
return new com.aliyun.sts20150401.Client(config);
}
/**
* Obtain an STS temporary credential.
* @return An AssumeRoleResponseBodyCredentials object.
*/
public static AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials getCredential() throws Exception {
com.aliyun.sts20150401.Client client = WebController.createStsClient();
com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()
// Required. Make sure that the OSS_STS_ROLE_ARN environment variable is set in your code's runtime environment.
.setRoleArn(System.getenv("OSS_STS_ROLE_ARN"))
.setRoleSessionName("yourRoleSessionName");// A custom session name.
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
try {
// If you copy this code to run, print the API return value.
AssumeRoleResponse response = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
// The credentials object contains the AccessKeyId, AccessKeySecret, and SecurityToken.
return response.body.credentials;
} catch (TeaException error) {
// This is for demonstration only. Handle exceptions with caution and do not ignore them in your project.
// Error message
System.out.println(error.getMessage());
// Diagnostic address
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
}
// Return a default error response object to avoid returning null.
AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials defaultCredentials = new AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials();
defaultCredentials.accessKeyId = "ERROR_ACCESS_KEY_ID";
defaultCredentials.accessKeySecret = "ERROR_ACCESS_KEY_SECRET";
defaultCredentials.securityToken = "ERROR_SECURITY_TOKEN";
return defaultCredentials;
}
@GetMapping("/get_post_signature_for_oss_upload")
public ResponseEntity<Map<String, String>> getPostSignatureForOssUpload() throws Exception {
AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials sts_data = getCredential();
String accesskeyid = sts_data.accessKeyId;
String accesskeysecret = sts_data.accessKeySecret;
String securitytoken = sts_data.securityToken;
// Get the date for x-oss-credential. This is the current date in yyyyMMdd format.
ZonedDateTime today = ZonedDateTime.now().withZoneSameInstant(java.time.ZoneOffset.UTC);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String date = today.format(formatter);
// Get x-oss-date.
ZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(java.time.ZoneOffset.UTC);
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'");
String x_oss_date = now.format(formatter2);
// Step 1: Create a policy.
String x_oss_credential = accesskeyid + "/" + date + "/" + region + "/oss/aliyun_v4_request";
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> policy = new HashMap<>();
policy.put("expiration", generateExpiration(expire_time));
List<Object> conditions = new ArrayList<>();
Map<String, String> bucketCondition = new HashMap<>();
bucketCondition.put("bucket", bucket);
conditions.add(bucketCondition);
Map<String, String> securityTokenCondition = new HashMap<>();
securityTokenCondition.put("x-oss-security-token", securitytoken);
conditions.add(securityTokenCondition);
Map<String, String> signatureVersionCondition = new HashMap<>();
signatureVersionCondition.put("x-oss-signature-version", "OSS4-HMAC-SHA256");
conditions.add(signatureVersionCondition);
Map<String, String> credentialCondition = new HashMap<>();
credentialCondition.put("x-oss-credential", x_oss_credential); // Replace with your actual AccessKey ID.
conditions.add(credentialCondition);
Map<String, String> dateCondition = new HashMap<>();
dateCondition.put("x-oss-date", x_oss_date);
conditions.add(dateCondition);
conditions.add(Arrays.asList("content-length-range", 1, 10240000));
conditions.add(Arrays.asList("eq", "$success_action_status", "200"));
conditions.add(Arrays.asList("starts-with", "$key", upload_dir));
policy.put("conditions", conditions);
String jsonPolicy = mapper.writeValueAsString(policy);
// Step 2: Construct the string to sign.
String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes()));
// System.out.println("stringToSign: " + stringToSign);
// Step 3: Calculate the signing key.
byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), date);
byte[] dateRegionKey = hmacsha256(dateKey, region);
byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
// System.out.println("signingKey: " + BinaryUtil.toBase64String(signingKey));
// Step 4: Calculate the signature.
byte[] result = hmacsha256(signingKey, stringToSign);
String signature = BinaryUtil.toHex(result);
// System.out.println("signature:" + signature);
Map<String, String> response = new HashMap<>();
// Add the data to the map.
response.put("version", "OSS4-HMAC-SHA256");
response.put("policy", stringToSign);
response.put("x_oss_credential", x_oss_credential);
response.put("x_oss_date", x_oss_date);
response.put("signature", signature);
response.put("security_token", securitytoken);
response.put("dir", upload_dir);
response.put("host", host);
// Return a ResponseEntity with status code 200 (OK) to the web client for the PostObject operation.
return ResponseEntity.ok(response);
}
public static byte[] hmacsha256(byte[] key, String data) {
try {
// Initialize the HmacSHA256 key specification.
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
// Get an HmacSHA256 Mac instance.
Mac mac = Mac.getInstance("HmacSHA256");
// Initialize the Mac object with the key.
mac.init(secretKeySpec);
// Calculate the HMAC signature for the data.
byte[] hmacBytes = mac.doFinal(data.getBytes());
return hmacBytes;
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC-SHA256", e);
}
}
}
Python
Run the following commands to install dependencies.
pip install flask
pip install alibabacloud_tea_openapi alibabacloud_sts20150401 alibabacloud_credentials
The following sample code shows how to obtain a temporary access credential (STS token), construct an upload policy, and calculate a POST signature on the server.
from flask import Flask, render_template, jsonify
from alibabacloud_tea_openapi.models import Config
from alibabacloud_sts20150401.client import Client as Sts20150401Client
from alibabacloud_sts20150401 import models as sts_20150401_models
from alibabacloud_credentials.client import Client as CredentialClient
import os
import json
import base64
import hmac
import datetime
import time
import hashlib
app = Flask(__name__)
# Configure the OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, and OSS_STS_ROLE_ARN environment variables.
access_key_id = os.environ.get('OSS_ACCESS_KEY_ID')
access_key_secret = os.environ.get('OSS_ACCESS_KEY_SECRET')
role_arn_for_oss_upload = os.environ.get('OSS_STS_ROLE_ARN')
# A custom session name.
role_session_name = 'yourRoleSessionName'
# Replace with your actual bucket name, region ID, and host.
bucket = 'examplebucket'
region_id = 'cn-hangzhou'
host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'
# The expiration time in seconds.
expire_time = 3600
# The prefix (directory) for objects to be uploaded to OSS.
upload_dir = 'dir'
def hmacsha256(key, data):
"""
Calculates the HMAC-SHA256 hash value.
:param key: The key for calculating the hash, in bytes.
:param data: The data to be hashed, as a string.
:return: The calculated HMAC-SHA256 hash value, in bytes.
"""
try:
mac = hmac.new(key, data.encode(), hashlib.sha256)
hmacBytes = mac.digest()
return hmacBytes
except Exception as e:
raise RuntimeError(f"Failed to calculate HMAC-SHA256 due to {e}")
@app.route("/")
def hello_world():
return render_template('index.html')
@app.route('/get_post_signature_for_oss_upload', methods=['GET'])
def generate_upload_params():
# Initialize the configuration and pass the credentials directly.
config = Config(
region_id=region_id,
access_key_id=access_key_id,
access_key_secret=access_key_secret
)
# Create an STS client and obtain a temporary credential.
sts_client = Sts20150401Client(config=config)
assume_role_request = sts_20150401_models.AssumeRoleRequest(
role_arn=role_arn_for_oss_upload,
role_session_name=role_session_name
)
response = sts_client.assume_role(assume_role_request)
token_data = response.body.credentials.to_map()
# Use the temporary credential returned by STS.
temp_access_key_id = token_data['AccessKeyId']
temp_access_key_secret = token_data['AccessKeySecret']
security_token = token_data['SecurityToken']
now = int(time.time())
# Convert the timestamp to a datetime object.
dt_obj = datetime.datetime.utcfromtimestamp(now)
# Add 3 hours to the current time to set the request expiration time.
dt_obj_plus_3h = dt_obj + datetime.timedelta(hours=3)
# Request time.
dt_obj_1 = dt_obj.strftime('%Y%m%dT%H%M%S') + 'Z'
# Request date.
dt_obj_2 = dt_obj.strftime('%Y%m%d')
# Request expiration time.
expiration_time = dt_obj_plus_3h.strftime('%Y-%m-%dT%H:%M:%S.000Z')
# Construct the policy and generate the signature.
policy = {
"expiration": expiration_time,
"conditions": [
["eq", "$success_action_status", "200"],
{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
{"x-oss-credential": f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request"},
{"x-oss-security-token": security_token},
{"x-oss-date": dt_obj_1},
]
}
print(dt_obj_1)
policy_str = json.dumps(policy).strip()
# Step 2: Construct the string to sign.
stringToSign = base64.b64encode(policy_str.encode()).decode()
# Step 3: Calculate the signing key.
dateKey = hmacsha256(("aliyun_v4" + temp_access_key_secret).encode(), dt_obj_2)
dateRegionKey = hmacsha256(dateKey, "cn-hangzhou")
dateRegionServiceKey = hmacsha256(dateRegionKey, "oss")
signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request")
# Step 4: Calculate the signature.
result = hmacsha256(signingKey, stringToSign)
signature = result.hex()
# Construct the response data.
response_data = {
'policy': stringToSign, # The policy form field.
'x_oss_signature_version': "OSS4-HMAC-SHA256", # The signature version and algorithm. This is fixed to OSS4-HMAC-SHA256.
'x_oss_credential': f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request", # Specifies the credential scope.
'x_oss_date': dt_obj_1, # The request time.
'signature': signature, # The calculated signature.
'host': host,
'dir': upload_dir,
'security_token': security_token # The security token.
}
return jsonify(response_data)
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000) # If you need to listen on other addresses such as 0.0.0.0, you must add a server-side authentication mechanism.
Node.js
Run the following commands to install dependencies.
npm install ali-oss
npm install @alicloud/credentials
npm install express
The following sample code shows how to obtain a temporary access credential (STS token), construct an upload policy, and calculate a POST signature on the server.
const express = require('express');
const OSS = require('ali-oss');
const { STS } = require('ali-oss');
const { getCredential } = require('ali-oss/lib/common/signUtils');
const { getStandardRegion } = require('ali-oss/lib/common/utils/getStandardRegion');
const { policy2Str } = require('ali-oss/lib/common/utils/policy2Str');
const app = express();
const PORT = process.env.PORT || 8000; // The port number for service requests.
// Set the static file directory.
app.use(express.static('templates'));
const GenerateSignature = async () => {
// Initialize the STS client.
let sts = new STS({
accessKeyId: process.env.OSS_ACCESS_KEY_ID, // Get the AccessKey ID of the RAM user from the environment variable.
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET // Get the AccessKey Secret of the RAM user from the environment variable.
});
// Call the assumeRole operation to obtain a temporary STS access credential.
const result = await sts.assumeRole(process.env.OSS_STS_ROLE_ARN, '', '3600', 'yourRoleSessionName'); // Get the RAM role ARN from the environment variable. The temporary access credential is valid for 3,600 seconds, and the role session name is a custom value, such as yourRoleSessionName.
// Extract the AccessKeyId, AccessKeySecret, and SecurityToken from the temporary access credential.
const accessKeyId = result.credentials.AccessKeyId;
const accessKeySecret = result.credentials.AccessKeySecret;
const securityToken = result.credentials.SecurityToken;
// Initialize the OSS client.
const client = new OSS({
bucket: 'examplebucket', // Replace with the name of the destination bucket.
region: 'cn-hangzhou', // Replace with the region of the destination bucket.
accessKeyId,
accessKeySecret,
stsToken: securityToken,
refreshSTSTokenInterval: 0,
refreshSTSToken: async () => {
const { accessKeyId, accessKeySecret, securityToken } = await client.getCredential();
return { accessKeyId, accessKeySecret, stsToken: securityToken };
},
});
// Create a form data map.
const formData = new Map();
// Set the signature expiration time to 10 minutes from the current time.
const date = new Date();
const expirationDate = new Date(date);
expirationDate.setMinutes(date.getMinutes() + 10);
// Format the date to a UTC time string that complies with ISO 8601.
function padTo2Digits(num) {
return num.toString().padStart(2, '0');
}
function formatDateToUTC(date) {
return (
date.getUTCFullYear() +
padTo2Digits(date.getUTCMonth() + 1) +
padTo2Digits(date.getUTCDate()) +
'T' +
padTo2Digits(date.getUTCHours()) +
padTo2Digits(date.getUTCMinutes()) +
padTo2Digits(date.getUTCSeconds()) +
'Z'
);
}
const formattedDate = formatDateToUTC(expirationDate);
// Generate x-oss-credential and set the form data.
const credential = getCredential(formattedDate.split('T')[0], getStandardRegion(client.options.region), client.options.accessKeyId);
formData.set('x_oss_date', formattedDate);
formData.set('x_oss_credential', credential);
formData.set('x_oss_signature_version', 'OSS4-HMAC-SHA256');
// Create the policy.
// This example policy lists only the required conditions.
const policy = {
expiration: expirationDate.toISOString(),
conditions: [
{ 'bucket': 'examplebucket'},
{ 'x-oss-credential': credential },
{ 'x-oss-signature-version': 'OSS4-HMAC-SHA256' },
{ 'x-oss-date': formattedDate },
],
};
// If an STS token exists, add it to the policy and form data.
if (client.options.stsToken) {
policy.conditions.push({ 'x-oss-security-token': client.options.stsToken });
formData.set('security_token', client.options.stsToken);
}
// Generate the signature and set the form data.
const signature = client.signPostObjectPolicyV4(policy, date);
formData.set('policy', Buffer.from(policy2Str(policy), 'utf8').toString('base64'));
formData.set('signature', signature);
// Return the form data.
return {
host: `http://${client.options.bucket}.oss-${client.options.region}.aliyuncs.com`,
policy: Buffer.from(policy2Str(policy), 'utf8').toString('base64'),
x_oss_signature_version: 'OSS4-HMAC-SHA256',
x_oss_credential: credential,
x_oss_date: formattedDate,
signature: signature,
dir: 'user-dir', // The prefix (directory) for the object to be uploaded to OSS.
security_token: client.options.stsToken
};
};
app.get('/get_post_signature_for_oss_upload', async (req, res) => {
try {
const result = await GenerateSignature();
res.json(result); // Return the generated signature data.
} catch (error) {
console.error('Error generating signature:', error);
res.status(500).send('Error generating signature');
}
});
app.listen(PORT, () => {
console.log(`Server is running on http://127.0.0.1:${PORT}`); // If you need to listen on other addresses such as 0.0.0.0, you must add a server-side authentication mechanism.
});
Go
Run the following commands to install dependencies.
go get -u github.com/aliyun/credentials-go
go mod tidy
The following sample code shows how to obtain a temporary access credential (STS token), construct an upload policy, and calculate a POST signature on the server.
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"hash"
"log"
"net/http"
"os"
"time"
"github.com/aliyun/credentials-go/credentials"
)
// Define global variables.
var (
region string
bucketName string
product = "oss"
)
// The PolicyToken struct stores the generated form data.
type PolicyToken struct {
Policy string `json:"policy"`
SecurityToken string `json:"security_token"`
SignatureVersion string `json:"x_oss_signature_version"`
Credential string `json:"x_oss_credential"`
Date string `json:"x_oss_date"`
Signature string `json:"signature"`
Host string `json:"host"`
Dir string `json:"dir"`
}
func main() {
// Define the default IP address and port string.
strIPPort := ":8000"
if len(os.Args) == 3 {
strIPPort = fmt.Sprintf("%s:%s", os.Args[1], os.Args[2])
} else if len(os.Args) != 1 {
fmt.Println("Usage : go run test1.go ")
fmt.Println("Usage : go run test1.go ip port ")
fmt.Println("")
os.Exit(0)
}
// Print the address and port on which the server is running.
fmt.Printf("server is running on %s \n", strIPPort)
// Register the function to handle root path requests.
http.HandleFunc("/", handlerRequest)
// Register the function to handle signature generation requests.
http.HandleFunc("/get_post_signature_for_oss_upload", handleGetPostSignature)
// Start the HTTP server.
err := http.ListenAndServe(strIPPort, nil)
if err != nil {
strError := fmt.Sprintf("http.ListenAndServe failed : %s \n", err.Error())
panic(strError)
}
}
// The handlerRequest function handles root path requests.
func handlerRequest(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
http.ServeFile(w, r, "templates/index.html")
return
}
http.NotFound(w, r)
}
// The handleGetPostSignature function handles signature generation requests.
func handleGetPostSignature(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
response := getPolicyToken()
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*") // Allow cross-origin requests.
w.Write([]byte(response))
return
}
http.NotFound(w, r)
}
// The getPolicyToken function generates the signature and credentials required for OSS uploads.
func getPolicyToken() string {
// Set the region of the bucket.
region = "cn-hangzhou"
// Replace with your bucket name.
bucketName = "examplebucket"
// Set the OSS upload address.
host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
// Set the upload directory.
dir := "user-dir"
config := new(credentials.Config).
SetType("ram_role_arn").
SetAccessKeyId(os.Getenv("OSS_ACCESS_KEY_ID")).
SetAccessKeySecret(os.Getenv("OSS_ACCESS_KEY_SECRET")).
SetRoleArn("OSS_STS_ROLE_ARN").
SetRoleSessionName("Role_Session_Name").
SetPolicy("").
SetRoleSessionExpiration(3600)
// Create a credential provider based on the configuration.
provider, err := credentials.NewCredential(config)
if err != nil {
log.Fatalf("NewCredential fail, err:%v", err)
}
// Obtain credentials from the credential provider.
cred, err := provider.GetCredential()
if err != nil {
log.Fatalf("GetCredential fail, err:%v", err)
}
// Construct the policy.
utcTime := time.Now().UTC()
date := utcTime.Format("20060102")
expiration := utcTime.Add(1 * time.Hour)
policyMap := map[string]any{
"expiration": expiration.Format("2006-01-02T15:04:05.000Z"),
"conditions": []any{
map[string]string{"bucket": bucketName},
map[string]string{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
map[string]string{"x-oss-credential": fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product)},
map[string]string{"x-oss-date": utcTime.Format("20060102T150405Z")},
map[string]string{"x-oss-security-token": *cred.SecurityToken},
},
}
// Convert the policy to JSON format.
policy, err := json.Marshal(policyMap)
if err != nil {
log.Fatalf("json.Marshal fail, err:%v", err)
}
// Construct the string to sign.
stringToSign := base64.StdEncoding.EncodeToString([]byte(policy))
hmacHash := func() hash.Hash { return sha256.New() }
// Construct the signing key.
signingKey := "aliyun_v4" + *cred.AccessKeySecret
h1 := hmac.New(hmacHash, []byte(signingKey))
io.WriteString(h1, date)
h1Key := h1.Sum(nil)
h2 := hmac.New(hmacHash, h1Key)
io.WriteString(h2, region)
h2Key := h2.Sum(nil)
h3 := hmac.New(hmacHash, h2Key)
io.WriteString(h3, product)
h3Key := h3.Sum(nil)
h4 := hmac.New(hmacHash, h3Key)
io.WriteString(h4, "aliyun_v4_request")
h4Key := h4.Sum(nil)
// Generate the signature.
h := hmac.New(hmacHash, h4Key)
io.WriteString(h, stringToSign)
signature := hex.EncodeToString(h.Sum(nil))
// Construct the form to be returned to the client.
policyToken := PolicyToken{
Policy: stringToSign,
SecurityToken: *cred.SecurityToken,
SignatureVersion: "OSS4-HMAC-SHA256",
Credential: fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", *cred.AccessKeyId, date, region, product),
Date: utcTime.UTC().Format("20060102T150405Z"),
Signature: signature,
Host: host, // The OSS upload address.
Dir: dir, // The upload directory.
}
response, err := json.Marshal(policyToken)
if err != nil {
fmt.Println("json err:", err)
}
return string(response)
}
PHP
Run the following command to install dependencies.
composer install
The following sample code shows how to obtain a temporary access credential (STS token), construct an upload policy, and calculate a POST signature on the server.
<?php
// Import the Alibaba Cloud SDK.
require_once __DIR__ . '/vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Sts\Sts;
// Disable error display.
ini_set('display_errors', '0');
$bucket = 'examplebucket'; // Replace with your bucket name.
$region_id = 'cn-hangzhou'; // Replace with the region of your bucket.
$host = 'http://examplebucket.oss-cn-hangzhou.aliyuncs.com'; // Replace with your bucket's domain name.
$expire_time = 3600; // The expiration time in seconds.
$upload_dir = 'user-dir'; // The prefix (directory) for uploaded objects.
// Calculate HMAC-SHA256.
function hmacsha256($key, $data) {
return hash_hmac('sha256', $data, $key, true);
}
// Handle the request to get the POST signature.
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/get_post_signature_for_oss_upload') {
AlibabaCloud::accessKeyClient(getenv('OSS_ACCESS_KEY_ID'), getenv('OSS_ACCESS_KEY_SECRET'))
->regionId('cn-hangzhou')
->asDefaultClient();
// Create an STS request.
$request = Sts::v20150401()->assumeRole();
// Initiate the STS request and get the result.
// Set <YOUR_ROLE_SESSION_NAME> to a custom session name, such as oss-role-session.
// Replace <YOUR_ROLE_ARN> with the ARN of a RAM role that has permission to upload files to the specified OSS bucket.
$result = $request
->withRoleSessionName('oss-role-session')
->withDurationSeconds(3600)
->withRoleArn(getenv('OSS_STS_ROLE_ARN'))
->request();
// Get the credential information from the STS request result.
$tokenData = $result->get('Credentials');
// Construct the JSON data to return.
$tempAccessKeyId = $tokenData['AccessKeyId'];
$tempAccessKeySecret = $tokenData['AccessKeySecret'];
$securityToken = $tokenData['SecurityToken'];
$now = time();
$dtObj = gmdate('Ymd\THis\Z', $now);
$dtObj1 = gmdate('Ymd', $now);
$dtObjPlus3h = gmdate('Y-m-d\TH:i:s.u\Z', strtotime('+3 hours', $now));
// Construct the policy.
$policy = [
"expiration" => $dtObjPlus3h,
"conditions" => [
["x-oss-signature-version" => "OSS4-HMAC-SHA256"],
["x-oss-credential" => "{$tempAccessKeyId}/{$dtObj1}/cn-hangzhou/oss/aliyun_v4_request"],
["x-oss-security-token" => $securityToken],
["x-oss-date" => $dtObj],
]
];
$policyStr = json_encode($policy);
// Construct the string to sign.
$stringToSign = base64_encode($policyStr);
// Calculate the signing key.
$dateKey = hmacsha256(('aliyun_v4' . $tempAccessKeySecret), $dtObj1);
$dateRegionKey = hmacsha256($dateKey, 'cn-hangzhou');
$dateRegionServiceKey = hmacsha256($dateRegionKey, 'oss');
$signingKey = hmacsha256($dateRegionServiceKey, 'aliyun_v4_request');
// Calculate the signature.
$result = hmacsha256($signingKey, $stringToSign);
$signature = bin2hex($result);
// Return the signature data.
$responseData = [
'policy' => $stringToSign,
'x_oss_signature_version' => "OSS4-HMAC-SHA256",
'x_oss_credential' => "{$tempAccessKeyId}/{$dtObj1}/cn-hangzhou/oss/aliyun_v4_request",
'x_oss_date' => $dtObj,
'signature' => $signature,
'host' => $host,
'dir' => $upload_dir,
'security_token' => $securityToken
];
header('Content-Type: application/json');
echo json_encode($responseData);
exit;
}
// Home page route.
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/') {
echo file_get_contents(__DIR__ . '/public/index.html');
exit;
}
// Other routes.
http_response_code(404);
echo json_encode(['message' => 'Not Found']);
exit;
?>
Step 3: Configure the web client
Client-side form upload
After the web client receives the required information from the application server, it builds an HTML form request. This request communicates directly with OSS to upload the file.
Web client: Sample response
The application server returns the STS token and the upload policy to the web client.
{
"dir": "user-dirs",
"host": "http://examplebucket.oss-cn-hangzhou.aliyuncs.com",
"policy": "eyJl****",
"security_token": "CAIS****",
"signature": "9103****",
"x_oss_credential": "STS.NSpW****/20241127/cn-hangzhou/oss/aliyun_v4_request",
"x_oss_date": "20241127T060941Z",
"x_oss_signature_version": "OSS4-HMAC-SHA256"
}
The following table describes each field in the response body.
|
Parameter |
Description |
|
dir |
Specifies the required object name prefix for uploads. |
|
host |
The domain name of the destination bucket. |
|
policy |
The policy used for browser-based form uploads. For more information, see Post Policy. |
|
security_token |
The temporary credential used for authentication, provided by STS. |
|
signature |
The signature generated from the policy. For more information, see Post Signature. |
|
x_oss_credential |
Specifies the parameter set used to derive the signing key. |
|
x_oss_date |
The request time in ISO 8601 format, for example, |
|
x_oss_signature_version |
The signature version and algorithm. The value is fixed at OSS4-HMAC-SHA256. |
-
The form request includes the file content and the parameters returned by the application server.
-
With this request, the web client communicates directly with OSS to upload the file.
-
Except for the file form field, all other form fields, including key, must not exceed 8 KB.
-
By default, web-based uploads overwrite objects with the same name. To prevent objects from being overwritten, add the x-oss-forbid-overwrite form field to the request and set its value to true. If an object with the same name already exists in OSS, the upload fails and OSS returns a FileAlreadyExists error.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Generate a signature on the server to upload a file to OSS</title>
</head>
<body>
<div class="container">
<form>
<div class="mb-3">
<label for="file" class="form-label">Select a file:</label>
<input type="file" class="form-control" id="file" name="file" required />
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const form = document.querySelector("form");
const fileInput = document.querySelector("#file");
form.addEventListener("submit", (event) => {
event.preventDefault();
const file = fileInput.files[0];
if (!file) {
alert('Please select a file to upload.');
return;
}
const filename = file.name;
fetch("/get_post_signature_for_oss_upload", { method: "GET" })
.then((response) => {
if (!response.ok) {
throw new Error("Failed to get signature");
}
return response.json();
})
.then((data) => {
let formData = new FormData();
formData.append("success_action_status", "200");
formData.append("policy", data.policy);
formData.append("x-oss-signature", data.signature);
formData.append("x-oss-signature-version", "OSS4-HMAC-SHA256");
formData.append("x-oss-credential", data.x_oss_credential);
formData.append("x-oss-date", data.x_oss_date);
formData.append("key", data.dir + file.name); // Object name
formData.append("x-oss-security-token", data.security_token);
formData.append("file", file); // file must be the last form field
return fetch(data.host, {
method: "POST",
body: formData
});
})
.then((response) => {
if (response.ok) {
console.log("Upload successful.");
alert("The file was uploaded successfully.");
} else {
console.log("Upload failed", response);
alert("Upload failed. Please try again later.");
}
})
.catch((error) => {
console.error("An error occurred:", error);
});
});
});
</script>
</body>
</html>
-
The HTML form contains a file input and a submit button.
-
When the form is submitted, the JavaScript code prevents the default submission and sends an AJAX request to the application server for the required signature information.
-
After receiving the signature information, the code creates a
FormDataobject with the required form fields. -
It then uses the
fetchmethod to send a POST request to the OSS URL to upload the file.
If the upload succeeds, the message "The file was uploaded successfully." is displayed. If the upload fails, an error message is displayed.
Verification
After deployment, access your application server to test the feature for direct uploads with signed URLs.
-
In a browser, access your application server. Click Select File, choose a file, and upload it.
-
On the Buckets page, open the bucket you created and verify that the uploaded object is present.
Recommended configurations
File upload policy
You can modify the policy in your code to set permissions and constraints for file uploads to OSS from an HTML form. The JSON-formatted policy lets you restrict uploads by setting parameters such as the allowed bucket name, object prefix, expiration time, allowed HTTP methods, content size limits, and content types.
{
"expiration": "2023-12-03T13:00:00.000Z",
"conditions": [
{"bucket": "examplebucket"},
{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
{"x-oss-credential": "AKIDEXAMPLE/20231203/cn-hangzhou/oss/aliyun_v4_request"},
{"x-oss-security-token": "CAIS******"},
{"x-oss-date": "20231203T121212Z"},
["content-length-range", 1, 10],
["eq", "$success_action_status", "201"],
["starts-with", "$key", "user/eric/"],
["in", "$content-type", ["image/jpeg", "image/png"]],
["not-in", "$cache-control", ["no-cache"]]
]
}
For more information about policy parameters, see Post Policy.
Server-side signing and upload callback
To receive metadata about uploaded files, such as the file name and size, configure an upload callback. After a file is uploaded, OSS sends the file information to your application server. For more information, see Server-side signing and direct upload with an upload callback.
Restrict CORS origins
For simplicity, the allowed origin was previously set to the wildcard character *. As a security best practice, you should replace the wildcard with the specific URL of your application server. This ensures that only cross-origin requests from your server are authorized.
|
Parameter |
Sample value |
|
Origin |
|
|
Allowed Methods |
POST, PUT, GET |
|
Allowed Headers |
* |
Clean up resources
In this solution, you created one ECS instance, one OSS bucket, one RAM user, and one RAM role. After you finish testing, clean up these resources to avoid ongoing charges or security risks.
Release the ECS instance
If you no longer need the instance, release it. After you release the instance, billing stops and you cannot recover its data.
-
Go to the Instances page in the ECS console. Find the target ECS instance by region and instance ID, and then click
in the Actions column. -
Choose Release. In the menu that appears, click Release.
-
Confirm the instance details, select Release Now, and then click Next.
-
Review the associated resources to be released, acknowledge the related data risks, and then click Confirm.
-
The system disk and any assigned public IP address are released along with the instance.
-
Security groups, vSwitches, and VPCs are not released with the instance. These resources are free of charge, but you can delete them if they are no longer needed.
-
EIPs are not released with the instance and continue to incur charges. Delete them separately if they are no longer needed.
Delete the OSS bucket
-
Log on to the OSS console.
-
Click Buckets, and then click the name of the target OSS bucket.
-
Delete all objects in the bucket.
-
In the navigation pane on the left, click Delete Bucket and follow the on-screen instructions.
Delete the RAM user
-
Log on to the RAM console as a RAM user with admin privileges.
-
In the navigation pane on the left, choose .
-
On the Users page, find the target RAM user and click Delete in the Actions column.
Alternatively, select multiple RAM users and click Delete User below the list to move them all to the Recycle Bin.
-
In the Delete User dialog box, carefully review the impact of the deletion, enter the name of the target RAM user, and then click Move to Recycle Bin.
Delete the RAM role
-
Log on to the RAM console as a RAM user with admin privileges.
-
In the navigation pane on the left, choose .
-
On the Roles page, find the target RAM role and click Delete Role in the Actions column.
-
In the Delete Role dialog box, enter the RAM role name and click Delete Role.
NoteIf the RAM role has policies attached, deleting the role also detaches them.
FAQ
Multipart and resumable upload
This solution uses form upload and does not support multipart or resumable uploads. To use these methods, see Resumable upload and Multipart upload.
Prevent file overwrite
Set the x-oss-forbid-overwrite parameter to true in the upload form fields. For example:
formData.append('x-oss-forbid-overwrite', 'true');