Upload objects directly from a web client to OSS by using the PostObject operation with server-generated signatures. This approach supports upload callbacks and policies to control uploads.
Solution overview
This workflow has three steps:
This process uses temporary access credentials to avoid exposing the application server's AccessKey pair.
-
Configure OSS: Create a bucket and configure cross-origin resource sharing (CORS) rules to allow cross-origin requests from web clients.
-
Configure the server: Generate a time-limited signature using access credentials and a policy with conditions such as the bucket name, directory path, and expiration time.
-
Configure the web client: Create an HTML form to upload objects directly to OSS. OSS parses the callback settings and sends a POST callback request to the application server.
Sample projects
Procedure
Step 1: Configure OSS
Step 1: Create a bucket
Create a bucket to store files uploaded from the web client.
-
Log in to the OSS console.
-
In the left navigation pane, click Buckets, then click Create Bucket.
-
In the Create Bucket panel, select Quick Create and configure the following parameters.
Parameter
Example value
Bucket Name
web-direct-upload-callback
Region
China (Hangzhou)
-
Click Create.
Step 2: Configure a CORS rule
Configure a CORS rule for your OSS bucket.
-
Go to the Buckets page and click the name of the target bucket.
-
On the CORS page, click Create Rule.
-
In the Create Rule panel, configure the CORS rule as follows.
Parameter
Example value
Origin
*
Allowed Methods
POST, PUT, GET
Allowed Headers
*
-
Click OK.
Step 2: Configure the server
If you already have a server, skip the preparations and go to User permissions.
Create an ECS instance
Step 1: Create an ECS instance
Go to the Custom Launch page and configure the following resources.
-
Select a region and billing method
-
Select a billing method. This topic uses pay-as-you-go.
-
Select a region close to your end-users. This topic uses China (Hangzhou).
In the Billing method section, select pay-as-you-go.
-
-
Create a VPC and a vSwitch
After creating the VPC and vSwitch, return to the ECS instance creation page, refresh it, and select them.
NoteYou can create a vSwitch when you create the VPC.
On the Create Virtual Private Cloud page, set Name to
ProjectA-VPC. For IPv4 CIDR block, select Enter IPv4 CIDR Block Manually and enter192.168.0.0/16. For IPv6 CIDR block, select No IPv6.In the vSwitch section, set Name to
ProjectA-vSwitch. For Availability Zone, select Hangzhou Zone H. Set IPv4 CIDR block to192.168.10.0/24, and then click OK.
-
Select an instance type and an image
This tutorial uses the
ecs.e-c1m1.largeinstance type and theAlibaba Cloud Linux 3.2104 LTS 64-bitpublic image.In the Instance type section, on the All generations tab, search for and select the
ecs.e-c1m1.largeinstance type. In the Image section, on the Public image tab, select Alibaba Cloud Linux as the operating system and 3.2104 LTS 64-bit as the version.
-
Configure storage
This tutorial requires only a system disk. No data disk is needed.
For the system disk, select ESSD. Set the capacity to 40 GiB and the performance level to PL0 (maximum IOPS per disk: 10,000). Select the Release with instance checkbox.
-
Assign a public IP address
This instance requires internet access. This tutorial assigns a public IP address during creation. Alternatively, Associate an EIP with a cloud resource after creation.
Note-
Without a public IP address, you cannot connect to the instance over the internet or verify the web service deployment.
-
This tutorial uses pay-by-traffic billing, which charges only for outbound data. Public bandwidth billing.
Set Peak bandwidth to 5 Mbps.
-
-
Create a security group
A security group controls inbound and outbound traffic for your ECS instance. Open the following ports to allow inbound traffic.
Port range: SSH (22), RDP (3389), HTTP (80), and HTTPS (443).
Note-
The Port range parameter specifies the ports required by the applications that run on the ECS instance.
-
By default, the security group allows traffic from all IP addresses (0.0.0.0/0). After creation, restrict traffic to specific IP ranges. Modify a security group rule.
For Security group type, select Basic security group.
-
-
Create a key pair
-
After creating a key pair, download and save the private key to connect to the ECS instance later. Return to the instance creation page, refresh, and select the key pair.
-
The
rootuser has full system privileges. Logging in asrootposes security risks. Useecs-useras the logon username.NoteThe private key file downloads automatically. Save the
.pemfile from your browser's download history.Click the Create a key pair link to create a new key pair. Then, in the Key pair drop-down list, select the key pair you just created, such as
ecs-test.
-
-
Create and view the ECS instance
Click Create Order and then click Console to view your new ECS instance. Record the following information:
-
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 access and verify your deployed web service.
In the instance list of the ECS console, you can find the Instance ID, Region, and Public IP address in their respective columns.
-
Step 2: Connect to the ECS instance
-
On the Instances page of the ECS console, find the instance that you created based on its region and ID. In the Actions column, click Connect.
-
In the Remote connection dialog box, under the Workbench option, click Sign in now.
-
In the Log on to instance dialog box, set Connection method to Terminal and Authentication method to SSH key-based authentication. Enter or upload the private key file that you downloaded when you created the key pair, and then click Log In. You are now logged in to the ECS instance as
ecs-user.NoteCheck your browser's download history for the
.pemprivate key file. -
Successful logon output:
Welcome to Alibaba Cloud Elastic Compute Service ! Last login: Sun Sep 29 15:35:22 2024 from xxx [ecs-user@ixxx ~]$
User permissions
Create a RAM user and grant the required permissions before deployment to prevent upload failures.
Step 1: Create a RAM user
Create a RAM user and obtain its AccessKey as a long-term credential for the server application.
-
Log on to the RAM console by using 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 for a RAM user is displayed only once, during creation, and cannot be retrieved later. Be sure to store it securely.
-
Click Copy in the Actions column to save the AccessKey (AccessKey ID and AccessKey secret).
Step 2: Grant AssumeRole permission
Grant the RAM user permission to call the STS AssumeRole operation to obtain temporary credentials.
-
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 Add Permissions page, select the AliyunSTSAssumeRoleAccess system policy.
NoteThe AliyunSTSAssumeRoleAccess policy grants permission to call the STS AssumeRole operation. This is separate from the OSS access permissions granted through the temporary credential.
Set Resource Scope to Account Level, and then click OK.
-
Click Confirm Authorization.
Step 3: Create a RAM role
Create a RAM role for your Alibaba Cloud account and obtain its Alibaba Cloud Resource Name (ARN).
-
In the left-side navigation pane, choose Identities > Roles.
-
Click Create Role. For the trusted entity type, select Alibaba Cloud Account.
-
Select Current Alibaba Cloud account and click OK.
-
Enter a role name and click OK.
-
On the RAM role management page, click Copy to save the ARN of the role.
Step 4: Create a policy for file uploads
Create a custom policy that restricts the RAM role to uploading objects to a specified bucket.
-
In the left-side navigation pane, choose Permissions > Policies.
-
Click Create Policy.
-
On the Create Policy page, click the JSON tab. In the policy document, replace
<BucketName>withweb-direct-upload, the name of the bucket you created previously.{ "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 Name for the policy and click OK.
Step 5: Grant permissions to the RAM role
Attach the custom policy to the RAM role.
-
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 Add Permissions page, select the Custom Policy tab, and then select the custom policy that you created.
Set Resource Scope to Account Level.
-
Click OK.
2. Get credentials and signature
Configure accessKeyId, accessKeySecret, and roleArn as environment variables to avoid hardcoding credentials in your code.
Add the following environment variables.
Linux
-
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 check if the environment variables are set.
echo $OSS_ACCESS_KEY_ID echo $OSS_ACCESS_KEY_SECRET echo $OSS_STS_ROLE_ARN
macOS
-
Run the following command in the terminal to check the default shell type.
echo $SHELL -
Follow the steps for your default shell type.
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 check if 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 check if 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.
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 Command Prompt window.
-
In the new Command Prompt window, run the following commands to check if 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 by using Signature Version 4 (recommended). The policy form fields topic lists available policy conditions.
Java
In your Maven project, add the following dependencies.
<!-- 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>
Use the following sample code to obtain temporary access credentials on the server, calculate a POST signature, and set up an upload callback.
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.codehaus.jettison.json.JSONObject;
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 the bucket name, region ID, and host with your actual values.
String bucket = "examplebucket";
String region = "cn-hangzhou";
String host = "http://examplebucket.oss-cn-hangzhou.aliyuncs.com";
// The URL for the upload callback. This must be a public URL. It is used for communication between your application server and OSS. After a file is uploaded, OSS sends the upload information to your application server through this URL.
String callbackUrl = "http://oss-demo.aliyuncs.com:23450/callback"; // The URL of the server that receives callback requests. Example: http://oss-demo.aliyuncs.com:23450/callback.
// The prefix for files 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, for example, "2014-12-01T12:00:00.000Z".
*/
public static String generateExpiration(long seconds) {
long now = Instant.now().getEpochSecond();
long expirationTime = now + seconds;
Instant instant = Instant.ofEpochSecond(expirationTime);
ZoneId zone = ZoneOffset.UTC;
ZonedDateTime zonedDateTime = instant.atZone(zone);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
String formattedDate = zonedDateTime.format(formatter);
return formattedDate;
}
// Initializes the STS client.
public static com.aliyun.sts20150401.Client createStsClient() throws Exception {
// Leaking your project code can expose your AccessKey pair, compromising the security of all resources under your account. The following sample code is for reference only.
// We recommend using the more secure STS method.
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// Required. Ensure that the OSS_ACCESS_KEY_ID environment variable is set in your execution environment.
.setAccessKeyId(System.getenv("OSS_ACCESS_KEY_ID"))
// Required. Ensure that the OSS_ACCESS_KEY_SECRET environment variable is set in your execution 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);
}
// Obtains temporary credentials from STS.
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. Ensure that the OSS_STS_ROLE_ARN environment variable is set in your execution 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 {
// When running this code, print the API return value for debugging.
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 purposes only. Handle exceptions with caution and do not ignore them in your project.
System.out.println(error.getMessage());
System.out.println(error.getData().get("Recommend"));
com.aliyun.teautil.Common.assertAsString(error.message);
}
// Returns 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 current date in yyyyMMdd format, used for the x-oss-credential field.
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()));
// 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");
// Step 4: Calculate the signature.
byte[] result = hmacsha256(signingKey, stringToSign);
String signature = BinaryUtil.toHex(result);
// Step 5: Configure the callback.
JSONObject jasonCallback = new JSONObject();
jasonCallback.put("callbackUrl", callbackUrl);
jasonCallback.put("callbackBody","filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
Map<String, String> response = new HashMap<>();
// Add 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);
response.put("callback", base64CallbackBody);
// 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 {
// Initializes the HMAC key specification, sets the algorithm to HmacSHA256, and uses the provided key.
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
// Obtains a Mac instance and uses the getInstance method to specify the HmacSHA256 algorithm.
Mac mac = Mac.getInstance("HmacSHA256");
// Initializes the Mac object with the key.
mac.init(secretKeySpec);
// Calculates the HMAC hash of 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 command to install dependencies.
pip install flask
pip install alibabacloud_tea_openapi alibabacloud_sts20150401 alibabacloud_credentials
Use the following sample code to obtain temporary access credentials from STS, build an upload policy, calculate a POST signature, and set up a callback.
from flask import Flask, render_template, jsonify, request
from alibabacloud_tea_openapi.models import Config
from alibabacloud_sts20150401.client import Client as Sts20150401Client
from alibabacloud_sts20150401 import models as sts_20150401_models
import os
import json
import base64
import hmac
import datetime
import time
import hashlib
import oss2
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 the 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 for files uploaded to OSS.
upload_dir = 'dir'
def hmacsha256(key, data):
"""
A function to calculate an 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 by directly passing the credentials.
config = Config(
region_id=region_id,
access_key_id=access_key_id,
access_key_secret=access_key_secret
)
# Create an STS client and obtain temporary credentials.
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 credentials 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)
# Set the request expiration time to 3 hours from the current 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')
# Define a function to Base64-encode the callback parameters.
def encode_callback(callback_params):
cb_str = json.dumps(callback_params).strip()
return oss2.compat.to_string(base64.b64encode(oss2.compat.to_bytes(cb_str)))
# Build the callback configuration and Base64-encode it.
callback_config = {
"callbackUrl": "http://oss-demo.aliyuncs.com:23450/callback", # The URL of your callback server.
"callbackBody": "bucket=${bucket}&object=${object}&etag=${etag}&size=${size}",
"callbackBodyType": "application/x-www-form-urlencoded"
}
encoded_callback = encode_callback(callback_config)
# Build 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},
]
}
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()
# Prepare the response data.
response_data = {
'policy': stringToSign, # The form field.
'x_oss_signature_version': "OSS4-HMAC-SHA256", # The signature version and algorithm. The value is fixed at OSS4-HMAC-SHA256.
'x_oss_credential': f"{temp_access_key_id}/{dt_obj_2}/cn-hangzhou/oss/aliyun_v4_request", # The parameter set that specifies the derived key.
'x_oss_date': dt_obj_1, # The request time.
'signature': signature, # The signature information.
'host': host,
'dir': upload_dir,
'security_token': security_token, # The security token.
'callback': encoded_callback # The Base64-encoded callback configuration.
}
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 an authentication mechanism on the server.
Node.js
Run the following command to install dependencies.
npm install ali-oss
npm install @alicloud/credentials
npm install express
Use the following sample code to obtain temporary access credentials from STS, build an upload policy, calculate a POST signature, and set up a callback.
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 service request port.
// 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, // Obtain the AccessKey ID of the RAM user from environment variables.
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET // Obtain the AccessKey secret of the RAM user from environment variables.
});
// Call the assumeRole operation to obtain temporary access credentials from STS.
const result = await sts.assumeRole(process.env.OSS_STS_ROLE_ARN, '', '3600', 'yourRoleSessionName'); // Obtain the RAM role ARN from an environment variable, set the validity period of the temporary access credentials to 3,600 seconds, and specify a custom role session name.
// Extract the AccessKeyId, AccessKeySecret, and SecurityToken from the temporary access credentials.
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 your target bucket name.
region: 'cn-hangzhou', // Replace with the region of your target 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 compliant with the ISO 8601 standard.
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);
// The URL for the upload callback. This is used for communication between your application server and OSS. After a file is uploaded, OSS sends the upload information to your application server through this URL. For example, set callbackUrl to https://oss-demo.aliyuncs.com:23450.
// 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 a policy.
// The following policy contains the minimum required fields.
const policy = {
expiration: expirationDate.toISOString(),
conditions: [
{ 'bucket': 'examplebucket' }, // Replace with your target bucket name.
{ '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);
const callback = {
callbackUrl: 'http://oss-demo.aliyuncs.com:23450/callback',// The URL of the server that receives callback requests. Example: http://oss-demo.aliyuncs.com:23450/callback.
callbackBody:// The content of the callback, such as the file ETag and resource MIME type.
"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
callbackBodyType: "application/x-www-form-urlencoded",// The content type of the callback.
};
// 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 for files uploaded to OSS.
callback: Buffer.from(JSON.stringify(callback)).toString("base64"),// Base64-encode the JSON object by using Buffer.from.
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 an authentication mechanism on the server.
});
Go
Run the following command to install dependencies.
go get -u github.com/aliyun/credentials-go
go mod tidy
Use the following sample code to obtain temporary access credentials from STS, build an upload policy, calculate a POST signature, and set up a callback.
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 is used to store 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"`
Callback string `json:"callback"`
}
type CallbackParam struct{
CallbackUrl string `json:"callbackUrl"`
CallbackBody string `json:"callbackBody"`
CallbackBodyType string `json:"callbackBodyType"`
}
func main() {
// Define the default IP address and port string.
strIPPort := ":8080"
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("Example : go run test1.go 11.22.**.** 80 ")
fmt.Println("Example : go run test1.go 0.0.0.0 8080 ")
fmt.Println("")
os.Exit(0)
}
// Print the address and port where the server is running.
fmt.Printf("server is running on %s \n", strIPPort)
// Register the function to handle requests for the root path.
http.HandleFunc("/", handlerRequest)
// Register the function to handle requests for obtaining signatures.
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 requests for the root path.
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 requests for obtaining signatures.
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 where the bucket is located.
region = "cn-hangzhou"
// Set the bucket name.
bucketName = "examplebucket"
// Set the OSS upload endpoint.
host := fmt.Sprintf("https://%s.oss-%s.aliyuncs.com", bucketName, region)
// Set the upload directory.
dir := "user-dir"
// callbackUrl is the URL of the server that receives upload callbacks. Replace the IP address and port with your actual information.
callbackUrl := "http://oss-demo.aliyuncs.com:23450/callback";
config := new(credentials.Config).
SetType("ram_role_arn").
SetAccessKeyId(os.Getenv("OSS_ACCESS_KEY_ID")).
SetAccessKeySecret(os.Getenv("OSS_ACCESS_KEY_SECRET")).
SetRoleArn(os.Getenv("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)
}
// Build 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() }
// Build 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))
var callbackParam CallbackParam
callbackParam.CallbackUrl = callbackUrl
callbackParam.CallbackBody = "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}"
callbackParam.CallbackBodyType = "application/x-www-form-urlencoded"
callback_str,err:=json.Marshal(callbackParam)
if err != nil {
fmt.Println("callback json err:", err)
}
callbackBase64 := base64.StdEncoding.EncodeToString(callback_str)
// Build 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 endpoint.
Dir: dir, // The upload directory.
Callback: callbackBase64, // The upload callback parameters.
}
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
Use the following sample code to obtain temporary access credentials from STS, build an upload policy, calculate a POST signature, and set up a callback.
<?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 domain name.
$expire_time = 3600; // Expiration time in seconds.
$upload_dir = 'user-dir'; // Prefix for uploaded files.
// $callbackUrl is the URL of the server that receives upload callbacks. Replace the IP address and port with your actual URL.
$callbackUrl = 'http://oss-demo.aliyuncs.com:23450/callback';
// Calculate HMAC-SHA256.
function hmacsha256($key, $data) {
return hash_hmac('sha256', $data, $key, true);
}
// Handle the request to obtain 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 obtain the result.
// Set to a custom session name, for example, oss-role-session.
// Replace with the ARN of a RAM role that has permissions to upload files to the specified OSS bucket.
$result = $request
->withRoleSessionName('oss-role-session')
->withDurationSeconds(3600)
->withRoleArn(getenv('OSS_STS_ROLE_ARN')) // Replace with your RAM role ARN.
->request();
// Obtain the credential information from the STS request result.
$tokenData = $result->get('Credentials');
// Build the returned JSON data.
$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));
// Build 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);
$callback_param = array(
'callbackUrl' => $callbackUrl,
'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
'callbackBodyType' => "application/x-www-form-urlencoded"
);
$callback_string = json_encode($callback_param);
$base64_callback_body = base64_encode($callback_string);
// 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,
'callback' => $base64_callback_body,
];
header('Content-Type: application/json');
echo json_encode($responseData);
exit;
}
// Homepage 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;
?>
The callback parameter is a Base64-encoded JSON string. To construct it, specify the callbackUrl (the URL of the server receiving the callback request) and the callbackBody (the content of the callback).
{"callbackUrl":"http://oss-demo.aliyuncs.com:23450/callback",
"callbackBody":"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
"callbackBodyType":"application/x-www-form-urlencoded"}
|
Parameter |
Description |
|
callbackUrl |
The URL of the application server that receives the callback from OSS. |
|
callbackBody |
The content of the callback request sent from OSS to the application server. This can include the file's name, size, and type, or an image's height and width. |
|
callbackBodyType |
The Valid values:
|
This example shows a basic callback configuration. Customize it based on your requirements. callback.
Step 3: Configure web client
Web client form upload
The web client constructs an HTML form request to upload files directly to OSS.
Response example
The application server returns the following response 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",
"callback":"eyJjYWxsYmFja1VybCI6Imh0dHA6Ly9vc3MtZGVtby5hbGl5dW5jcy5jb206MjM0NTAiLAoiY2FsbGJhY2tCb2R5IjoiZmlsZW5hbWU9JHtvYmplY3R9JnNpemU9JHtzaXplfSZtaW1lVHlwZT0ke21pbWVUeXBlfSZoZWlnaHQ9JHtpbWFnZUluZm8uaGVpZ2h0fSZ3aWR0aD0ke2ltYWdlSW5mby53aWR0aH0iLAoiY2FsbGJhY2tCb2R5VHlwZSI6ImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCJ9"
}
Response fields:
|
Parameter |
Description |
|
dir |
Restricts uploads to a specific file prefix. |
|
host |
The bucket domain name. |
|
policy |
The form upload policy. Post Policy. |
|
security_token |
The security token. |
|
signature |
The signature calculated from the policy. Post Signature. |
|
x_oss_credential |
Specifies the parameters for the derived key. |
|
x_oss_date |
The request timestamp in ISO 8601 format. Example: |
|
x_oss_signature_version |
The signature version and algorithm. The value is always OSS4-HMAC-SHA256. |
|
callback |
The body of the callback request. |
-
The form request includes the file's content and the parameters received from the application server.
-
The web client sends this data as a multipart/form-data POST request directly to OSS.
-
Except for the
fileform field, the size of all other form fields, includingkey, must not exceed 8 KB. -
By default, uploads overwrite existing objects with the same name. To prevent this, include the
x-oss-forbid-overwriteheader in the upload request and set its value totrue. If an object with the same name already exists, the upload fails, and OSS returns aFileAlreadyExistserror.
<!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 files to OSS</title>
</head>
<body>
<div class="container">
<form>
<div class="mb-3">
<label for="file" class="form-label">Select the 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 id="callback-info" class="mt-3" style="display: none;">
<h4>Callback information:</h4>
<pre id="callback-content"></pre>
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const form = document.querySelector("form");
const fileInput = document.querySelector("#file");
const callbackInfo = document.querySelector("#callback-info");
const callbackContent = document.querySelector("#callback-content");
form.addEventListener("submit", (event) => {
event.preventDefault();
const file = fileInput.files[0];
if (!file) {
alert('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 obtain the 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); // The file name.
formData.append("x-oss-security-token", data.security_token);
formData.append("callback", data.callback); // Add callback parameters.
formData.append("file", file); // The 'file' form field must be the last one.
return fetch(data.host, {
method: "POST",
body: formData
});
})
.then((response) => {
if (response.ok) {
console.log("Upload successful");
alert("File uploaded");
return response.json(); // Parse the callback information.
} else {
console.log("Upload failed with the following response:", response);
alert("Upload failed. Please try again later.");
}
})
.then((callbackData) => {
if (callbackData) {
callbackContent.textContent = JSON.stringify(callbackData, null, 2);
callbackInfo.style.display = "block";
}
})
.catch((error) => {
console.error("An error occurred:", error);
});
});
});
</script>
</body>
</html>
-
The HTML form contains a file input field and a submit button, allowing users to select a file and initiate the upload.
-
When the form is submitted, the JavaScript code prevents the default submission behavior. It then sends an AJAX request to the application server to fetch the required signature information.
-
After you obtain the signature information, construct a
FormDataobject that contains all the necessary form fields. -
Send a POST request to the URL of the OSS service using the
fetchmethod to upload the object.
Upon successful upload, a "File uploaded" message and any callback information are displayed. If the upload fails, an error message is shown.
Result verification
Test the upload feature after deployment.
-
In your browser, go to the server address, click the Select File button, select a file, and then upload it.
-
On the Buckets page, find your bucket and verify that the file was uploaded successfully.
Clean up resources
Delete the resources created in this tutorial to avoid ongoing charges.
Release the ECS instance
Releasing an instance stops billing and permanently deletes its data.
-
Go to the Instances page of the ECS console. Find the target ECS instance by its region and instance ID. In the Actions column, click
. -
Select Release. From the drop-down menu, select Release in the Instance Status section.
-
Verify that you have selected the correct instance, select Release Now, and then click Next.
-
Review the associated resources that will be released and acknowledge the data risks. Then, click OK.
-
The system disk and the assigned public IP address are released with the instance.
-
The security group, vSwitch, and VPC are not released with the instance. These resources are free of charge, so you can choose to delete them based on your business needs.
-
An EIP is not released with the instance and is not a free resource. You can choose to delete it based on your business needs.
Delete the bucket
-
Log on to the OSS console.
-
In the navigation pane on the left, click Buckets. Then, click the name of the target bucket.
-
Delete all objects in the bucket.
-
In the navigation pane on the left, click Delete Bucket.
Delete the RAM user
-
Log on to the RAM console as a RAM administrator.
-
In the navigation pane on the left, choose Identities > Users.
-
On the Users page, find the RAM user to delete and click Delete in the Actions column.
Alternatively, to delete multiple RAM users at once, select their checkboxes and click Delete User at the bottom of the list. This action moves the users to the recycle bin.
-
In the Delete User dialog box, review the impact of the deletion, enter the RAM user name for confirmation, and then click Move to Recycle Bin.
Delete the RAM role
-
Log on to the RAM console as a RAM administrator.
-
In the navigation pane on the left, choose Identities > Roles.
-
On the Roles page, find the RAM role to delete and click Delete Role in the Actions column.
-
In the Delete Role dialog box, enter the RAM role name for confirmation, and then click Delete Role.
NoteIf a policy is attached to the RAM role, deleting the role also detaches the policy.
FAQ
Batch upload from the front end
OSS does not provide a batch upload API. Upload objects individually in a loop using the same procedure.
Customize callback request headers
No. You can customize the callback body parameters, but not the request headers.