By default, the access control list of files in an OSS bucket is private, and only the file owner can upload files. However, the file owner can generate a presigned URL with temporary access privileges for a specific file, allowing others to upload files using the presigned URL within the validity period. This feature is suitable for scenarios such as authorized partners uploading contracts or users uploading profile pictures.
Notes
In this topic, the public endpoint of the China (Hangzhou) region is used. If you want to access OSS from other Alibaba Cloud services in the same region as OSS, use an internal endpoint. For more information about OSS regions and endpoints, see Regions and endpoints.
-
When generating a presigned URL for the PUT method, you must have the
oss:PutObject
permission. For more information, see RAM policy examples.NoteWhen you use OSS SDK for Java to generate a signed URL, the SDK uses a specific algorithm based on the key information stored on the local computer to calculate a signature and adds the signature to a URL to ensure the validity and security of the URL. The operations performed to calculate the signature and construct the URL are completed on the client. You do not need to send requests to the server over the network. This way, the caller does not need to be granted specific permissions to use OSS SDK for Java to generate a signed URL. However, to allow third-party users to perform relevant operations on the resources authorized by the signed URL, you must make sure that the caller that calls the API operations to generate the signed URL has the corresponding permissions.
-
A presigned URL can be accessed multiple times within its validity period, but there is a risk of file overwriting if multiple upload operations are performed. After the validity period expires, you need to perform Step 1 to regenerate the presigned URL to continue accessing the file.
-
Presigned URL uploads do not support uploading in FormData format. If you need to upload data using FormData, it is recommended to use OSS form upload.
Process overview
The process of uploading files using a presigned URL is as follows:
Detailed steps
Step 1: The bucket owner generates a PUT method pre-signed URL
The maximum validity period of a presigned URL generated by the SDK is 7 days. If you use an STS token to generate a presigned URL, the maximum validity period is 43,200 seconds (12 hours).
Java
For more information about the SDK, see Java upload files using presigned URLs.
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import java.net.URL;
import java.util.*;
import java.util.Date;
public class GetSignUrl {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object.
String objectName = "exampleobject.txt";
// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou.
String region = "cn-hangzhou";
// Create an OSSClient instance.
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
URL signedUrl = null;
try {
// Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour.
Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
// Generate a signed URL.
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
// Specify the validity period of the signed URL.
request.setExpiration(expiration);
// Generate a signed URL that allows HTTP PUT requests.
signedUrl = ossClient.generatePresignedUrl(request);
// Display the signed URL.
System.out.println("signed url for putObject: " + signedUrl);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
}
}
}
Go
For more information about the SDK, see Go upload files using presigned URLs.
package main
import (
"context"
"flag"
"log"
"time"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
// Specify the global variables.
var (
region string // The region in which the bucket is located.
bucketName string // The name of the bucket.
objectName string // The name of the object.
)
// Specify the init function used to initialize command line parameters.
func init() {
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
flag.StringVar(&objectName, "object", "", "The name of the object.")
}
func main() {
// Parse command line parameters.
flag.Parse()
// Check whether the bucket name is empty.
if len(bucketName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, bucket name required")
}
// Check whether the region is empty.
if len(region) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, region required")
}
// Check whether the object name is empty.
if len(objectName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, object name required")
}
// Load the default configurations and specify the credential provider and region.
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
// Create an OSS client.
client := oss.NewClient(cfg)
// Generate a signed URL for the PutObject request.
result, err := client.Presign(context.TODO(), &oss.PutObjectRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
//ContentType: oss.Ptr("text/txt"), // Make sure that the value of the ContentType parameter contained in the URL is the same as the ContentType value specified in the request.
//Metadata: map[string]string{"key1": "value1", "key2": "value2"}, // Make sure that the value of the Metadata parameter contained in the URL is the same as the Metadata value specified in the request.
},
oss.PresignExpires(10*time.Minute),
)
if err != nil {
log.Fatalf("failed to put object presign %v", err)
}
log.Printf("request method:%v\n", result.Method)
log.Printf("request expiration:%v\n", result.Expiration)
log.Printf("request url:%v\n", result.URL)
if len(result.SignedHeaders) > 0 {
// If you specify request headers when you generate a signed URL that allows HTTP PUT requests, make sure that the request headers are included in the PUT request initiated by using the signed URL.
log.Printf("signed headers:\n")
for k, v := range result.SignedHeaders {
log.Printf("%v: %v\n", k, v)
}
}
}
Python
For more information about the SDK, see Python upload files using presigned URLs.
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# Specify the region in which the bucket is located. Example: cn-hangzhou. This parameter is required if you use the V4 signature algorithm.
region = "cn-hangzhou"
# Specify the name of the bucket.
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
# Specify the full path of the object. Example: exampledir/exampleobject.txt. Do not include the bucket name in the full path.
object_name = 'exampledir/exampleobject.txt'
# Generate a signed URL and set the validity period of the signed URL to 60 seconds.
# By default, OSS identifies forward slashes (/) in the full path of an object as escape characters in the signing process. Therefore, the signed URL cannot be directly used.
# Set the slash_safe parameter to True. This way, OSS does not identify the forward slashes (/) in the full path of the object as escape characters. In this case, you can use the generated signed URL to upload the object.
url = bucket.sign_url('PUT', object_name, 60, slash_safe=True)
print ('Signed URL:', url)
Node.js
This section lists only common scenarios. For more information about how to generate a presigned URL with image processing parameters or a presigned URL with a version ID, see Node.js upload using presigned URLs.
const OSS = require("ali-oss");
// Specify a function used to generate a signed URL.
async function generateSignatureUrl(fileName) {
// Obtain the signed URL.
const client = await new OSS({
accessKeyId: 'yourAccessKeyId',
accessKeySecret: 'yourAccessKeySecret',
bucket: 'examplebucket',
region: 'oss-cn-hangzhou',
authorizationV4: true
});
return await client.signatureUrlV4('PUT', 3600, {
headers: {} // Specify the request headers based on the actual request headers.
}, fileName);
}
// Call the function and pass in the object name.
generateSignatureUrl('yourFileName').then(url => {
console.log('Generated Signature URL:', url);
}).catch(err => {
console.error('Error generating signature URL:', err);
});
PHP
This section lists only common scenarios. For more information about how to generate a presigned URL with a version ID, see PHP upload using presigned URLs.
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
$provider = new EnvironmentVariableCredentialsProvider();
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
$endpoint = "yourEndpoint";
// Specify the name of the bucket.
$bucket= "examplebucket";
// Specify the full path of the object. Do not include the bucket name in the full path of the object.
$object = "exampleobject.txt";
// Set the validity period of the signed URL to 600 seconds. Maximum value: 32400.
$timeout = 600;
try {
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
'signatureVersion'=>OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> "cn-hangzhou"
);
$ossClient = new OssClient($config);
// Generate the signed URL.
$signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT");
print_r($signedUrl);
} catch (OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
Android
For more information about the SDK, see Android upload files using presigned URLs.
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the source object. Do not include the bucket name in the full path. Example: exampleobject.txt.
String objectKey = "exampleobject.txt";
// Specify the contentType header.
String contentType = "application/octet-stream";
String url = null;
try {
// Generate a signed URL to upload the object.
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey);
// Set the validity period of the signed URL to 30 minutes.
request.setExpiration(30*60);
request.setContentType(contentType);
request.setMethod(HttpMethod.PUT);
url = oss.presignConstrainedObjectURL(request);
Log.d("url", url);
} catch (ClientException e) {
e.printStackTrace();
}
C++
For more information about the SDK, see C++ upload files using presigned URLs.
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* Initialize information about the account that is used to access OSS. */
/* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
std::string Endpoint = "yourEndpoint";
/* Specify the name of the bucket. Example: examplebucket. */
std::string BucketName = "examplebucket";
/* Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. */
std::string PutobjectUrlName = "exampledir/exampleobject.txt";
/* Initialize resources, such as network resources. */
InitializeSdk();
ClientConfiguration conf;
/* Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. */
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
/* Specify the validity period of the signed URL. */
std::time_t t = std::time(nullptr) + 1200;
/* Generate the signed URL. */
auto genOutcome = client.GeneratePresignedUrl(BucketName, PutobjectUrlName, t, Http::Put);
if (genOutcome.isSuccess()) {
std::cout << "GeneratePresignedUrl success, Gen url:" << genOutcome.result().c_str() << std::endl;
}
else {
/* Handle exceptions. */
std::cout << "GeneratePresignedUrl fail" <<
",code:" << genOutcome.error().Code() <<
",message:" << genOutcome.error().Message() <<
",requestId:" << genOutcome.error().RequestId() << std::endl;
return -1;
}
/* Release resources, such as network resources. */
ShutdownSdk();
return 0;
}
iOS
For more information about the SDK, see iOS upload files using presigned URLs.
// Specify the name of the bucket.
NSString *bucketName = @"examplebucket";
// Specify the name of the object.
NSString *objectKey = @"exampleobject.txt";
NSURL *file = [NSURL fileURLWithPath:@"<filePath>"];
NSString *contentType = [OSSUtil detemineMimeTypeForFilePath:file.absoluteString uploadName:objectKey];
__block NSString *urlString;
// Generate a signed URL with a validity period for uploading the object. In this example, the validity period of the URL is 30 minutes.
OSSTask *task = [client presignConstrainURLWithBucketName:bucketName
withObjectKey:objectKey
httpMethod:@"PUT"
withExpirationInterval:30 * 60
withParameters:@{}
contentType:contentType
contentMd5:nil];
[task continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
if (task.error) {
NSLog(@"presign error: %@", task.error);
} else {
urlString = task.result;
NSLog(@"url: %@", urlString);
}
return nil;
}];
.NET
For more information about the SDK, see .NET upload using presigned URLs.
using Aliyun.OSS;
using Aliyun.OSS.Common;
// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// Specify the name of the bucket. Example: examplebucket.
var bucketName = "examplebucket";
// Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt.
var objectName = "exampledir/exampleobject.txt";
var objectContent = "More than just cloud.";
// Create an OSSClient instance.
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
// Generate the signed URL.
var generatePresignedUriRequest = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Put)
{
// Specify the validity period of the signed URL. Default value: 3600. Unit: seconds.
Expiration = DateTime.Now.AddHours(1),
};
var signedUrl = client.GeneratePresignedUri(generatePresignedUriRequest);
}
catch (OssException ex)
{
Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
Console.WriteLine("Failed with error info: {0}", ex.Message);
}
C
For more information about the SDK, see C download files using presigned URLs.
#include "oss_api.h"
#include "aos_http_io.h"
/* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
const char *endpoint = "yourEndpoint";
/* Specify the name of the bucket. Example: examplebucket. */
const char *bucket_name = "examplebucket";
/* Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. */
const char *object_name = "exampledir/exampleobject.txt";
/* Specify the full path of the local file. */
const char *local_filename = "yourLocalFilename";
void init_options(oss_request_options_t *options)
{
options->config = oss_config_create(options->pool);
/* Use a char* string to initialize aos_string_t. */
aos_str_set(&options->config->endpoint, endpoint);
/* Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. */
aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
/* Specify whether to use CNAME. The value 0 indicates that CNAME is not used. */
options->config->is_cname = 0;
/* Configure network parameters, such as the timeout period. */
options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
/* Call the aos_http_io_initialize method in main() to initialize global resources, such as network and memory resources. */
if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
exit(1);
}
/* Create a memory pool to manage memory. aos_pool_t is equivalent to apr_pool_t. The code that is used to create a memory pool is included in the APR library. */
aos_pool_t *pool;
/* Create a memory pool. The value of the second parameter is NULL. This value specifies that the pool does not inherit other memory pools. */
aos_pool_create(&pool, NULL);
/* Create and initialize options. This parameter includes global configuration information, such as endpoint, access_key_id, access_key_secret, is_cname, and curl. */
oss_request_options_t *oss_client_options;
/* Allocate memory resources in the memory pool to the options. */
oss_client_options = oss_request_options_create(pool);
/* Initialize oss_client_options. */
init_options(oss_client_options);
/* Initialize the parameters. */
aos_string_t bucket;
aos_string_t object;
aos_string_t file;
aos_http_request_t *req;
apr_time_t now;
char *url_str;
aos_string_t url;
int64_t expire_time;
int one_hour = 3600;
aos_str_set(&bucket, bucket_name);
aos_str_set(&object, object_name);
aos_str_set(&file, local_filename);
expire_time = now / 1000000 + one_hour;
req = aos_http_request_create(pool);
req->method = HTTP_PUT;
now = apr_time_now();
/* Specify the validity period. Unit: microseconds * /
expire_time = now / 1000000 + one_hour;
/* Generate a signed URL. */
url_str = oss_gen_signed_url(oss_client_options, &bucket, &object, expire_time, req);
aos_str_set(&url, url_str);
printf("The signed URL used to upload the object: %s\n", url_str);
/* Release the memory pool. This operation releases memory resources allocated for the request. */
aos_pool_destroy(pool);
/* Release the allocated global resources. */
aos_http_io_deinitialize();
return 0;
}
Step 2: Upload files using the pre-signed URL generated by others with the PUT method.
Upload by using the curl command
curl -X PUT -T /path/to/local/file "https://exampleobject.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T083238Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"
Upload by using code
Java
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.*;
import java.net.URL;
import java.util.*;
public class SignUrlUpload {
public static void main(String[] args) throws Throwable {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
// Replace <signedUrl> with the generated signed URL.
URL signedUrl = new URL("<signedUrl>");
// Specify the full path of the local file that you want to upload. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs.
String pathName = "C:\\Users\\demo.txt";
try {
HttpPut put = new HttpPut(signedUrl.toString());
System.out.println(put);
HttpEntity entity = new FileEntity(new File(pathName));
put.setEntity(entity);
httpClient = HttpClients.createDefault();
response = httpClient.execute(put);
System.out.println("Upload status code:"+response.getStatusLine().getStatusCode());
if(response.getStatusLine().getStatusCode() == 200){
System.out.println("The object is uploaded by using the library.");
}
System.out.println(response.toString());
} catch (Exception e){
e.printStackTrace();
} finally {
response.close();
httpClient.close();
}
}
}
Python
import requests
def upload_file(signed_url, file_path):
try:
# Open the local file that you want to upload.
with open(file_path, 'rb') as file:
# Send a PUT request to upload the file.
response = requests.put(signed_url, data=file)
print(f "Upload status code:{response.status_code}")
if response.status_code == 200:
print("The object is uploaded by using the library.")
print(response.text)
except Exception as e:
print(f "An error occurred:{e}")
if __name__ == "__main__":
# Replace <signedUrl> with the generated signed URL.
signed_url = "<signedUrl>"
# Specify the full path of the local file. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs.
file_path = "C:\\Users\\demo.txt"
upload_file(signed_url, file_path)
Go
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func uploadFile(signedUrl, filePath string) error {
// Open the local file.
file, err := os.Open(filePath)
if err != nil {
return fmt.Errorf("Unable to open the local file: %w", err)
}
defer file.Close()
// Create a new HTTP client.
client := &http.Client{}
// Create a PUT request.
req, err := http.NewRequest("PUT", signedUrl, file)
if err != nil {
return fmt.Errorf("Failed to create the request: %w", err)
}
// Send the request.
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("Failed to send the request: %w", err)
}
defer resp.Body.Close()
// Read the response.
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("Failed to read the response: %w", err)
}
fmt.Printf("Upload status code: %d\n", resp.StatusCode)
if resp.StatusCode == 200 {
fmt.Println("The object is uploaded by using the library.")
}
fmt.Println(string(body))
return nil
}
func main() {
// Replace <signedUrl> with the generated signed URL.
signedUrl := "<signedUrl>"
// Specify the full path of the local file that you want to upload. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs.
filePath := "C:\\Users\\demo.txt"
err := uploadFile(signedUrl, filePath)
if err != nil {
fmt.Println('An error occurred:', err)
}
}
Node.js
const fs = require('fs');
const axios = require('axios');
async function uploadFile(signedUrl, filePath) {
try {
// Create a read stream.
const fileStream = fs.createReadStream(filePath);
// Send a PUT request to upload the local file.
const response = await axios.put(signedUrl, fileStream, {
headers: {
'Content-Type': 'application/octet-stream' // Specify the Content-Type parameter based on the actual scenario.
}
});
console.log ('Upload status code: ${response.status});
if (response.status === 200) {
console.log("The object is uploaded by using the library.");
}
console.log(response.data);
} catch (error) {
console.error ('An error occurred: ${error.message});
}
}
// Specify the main function.
(async () => {
// Replace <signedUrl> with the generated signed URL.
const signedUrl = '<signedUrl>';
// Specify the full path of the local file that you want to upload. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs.
const filePath = 'C:\\Users\\demo.txt';
await uploadFile(signedUrl, filePath);
})();
Browser.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload Example</title>
</head>
<body>
<h1>File Upload Example</h1>
<input type="file" id="fileInput" />
<button id="uploadButton">Upload File</button>
<script>
// Replace this with the actual presigned URL
const signedUrl = "<signedUrl>";
document.getElementById('uploadButton').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (file) {
try {
await upload(file, signedUrl);
} catch (error) {
console.error('Error during upload:', error);
alert('Upload failed: ' + error.message);
}
} else {
console.error('Please select a file');
alert('Please select a file to upload.');
}
});
const upload = async (file, presignedUrl) => {
const chunkSize = 1024 * 1024;
let start = 0;
let end = chunkSize;
while (start < file.size) {
const chunk = file.slice(start, end);
const response = await fetch(presignedUrl, {
method: 'PUT',
body: chunk
});
if (!response.ok) {
throw new Error(`Upload failed for chunk, status: ${response.status}`);
}
console.log('Chunk uploaded successfully');
start = end;
end = start + chunkSize;
}
console.log('File uploaded successfully');
};
</script>
</body>
</html>
C++
#include <iostream>
#include <fstream>
#include <curl/curl.h>
void uploadFile(const std::string& signedUrl, const std::string& filePath) {
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
// Specify the signed URL.
curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str());
// Set the request method to PUT.
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
// Open the local file.
FILE *file = fopen(filePath.c_str(), "rb");
if (!file) {
std::cerr << "Unable to open the file: " << filePath << std::endl;
return;
}
// Query the size of the local file.
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
// Specify the size of the local file.
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
// Specify the input file handle.
curl_easy_setopt(curl, CURLOPT_READDATA, file);
// Execute the request.
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
} else {
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
std::cout << "Upload status code: " << httpCode << std::endl;
if (httpCode == 200) {
std::cout << "The object is uploaded by using the library." << std::endl;
}
}
// Close the local file.
fclose(file);
// Clear the cURL handle.
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
int main() {
// Replace <signedUrl> with the generated signed URL.
std::string signedUrl = "<signedUrl>";
// Specify the full path of the local file that you want to upload. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs.
std::string filePath = "C:\\Users\\demo.txt";
uploadFile(signedUrl, filePath);
return 0;
}
Android
package com.example.signurlupload;
import android.os.AsyncTask;
import android.util.Log;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class SignUrlUploadActivity {
private static final String TAG = "SignUrlUploadActivity";
public void uploadFile(String signedUrl, String filePath) {
new UploadTask().execute(signedUrl, filePath);
}
private class UploadTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String signedUrl = params[0];
String filePath = params[1];
HttpURLConnection connection = null;
DataOutputStream dos = null;
FileInputStream fis = null;
try {
URL url = new URL(signedUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/octet-stream");
fis = new FileInputStream(filePath);
dos = new DataOutputStream(connection.getOutputStream());
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) != -1) {
dos.write(buffer, 0, length);
}
dos.flush();
dos.close();
fis.close();
int responseCode = connection.getResponseCode();
Log.d(TAG, "Upload status code: " + responseCode);
if (responseCode == 200) {
Log.d(TAG, "The object is uploaded by using the library.");
}
return "Object uploaded, status code: " + responseCode;
} catch (IOException e) {
e.printStackTrace();
return "Upload failed: " + e.getMessage();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
@Override
protected void onPostExecute(String result) {
Log.d(TAG, result);
}
}
public static void main(String[] args) {
SignUrlUploadActivity activity = new SignUrlUploadActivity();
// Replace <signedUrl> with the generated signed URL.
String signedUrl = "<signedUrl>";
// Specify the full path of the local file that you want to upload. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs.
String filePath = "C:\\Users\\demo.txt";
activity.uploadFile(signedUrl, filePath);
}
}
iOS
// Upload the object by using the signed URL.
NSURL * url = [NSURL URLWithString:urlString];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"PUT";
request.allHTTPHeaderFields = @{OSSHttpHeaderContentType: contentType};
NSURLSession * session = [NSURLSession sharedSession];
NSURLSessionTask * sessionTask = [session uploadTaskWithRequest:request
fromFile:file
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"upload error: %@", error);
return;
} else if (((NSHTTPURLResponse*)response).statusCode == 203 ||
((NSHTTPURLResponse*)response).statusCode >= 300) {
NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"upload error: %@", body);
return;
}
NSLog(@"upload success");
}];
[sessionTask resume];
Other scenarios
Upload files in sharding mode by using presigned URLs
Define upload policies by using presigned URLs (with headers)
Learn more
What is a pre-signed URL
A presigned URL is a secure link that temporarily authorizes access to a specific OSS file through signature encryption and validity period verification. When a presigned URL is generated, the local system encrypts parameters such as the resource path and expiration time based on the AK/SK key, generates signature parameters, and adds them to the URL to form a complete presigned URL. The typical format is: https://BucketName.Endpoint/Object?SignatureParameters
.
When a third party accesses the URL, OSS verifies the signature parameters. If the parameters are tampered with or expired, access is denied.
The following is an example of a presigned URL.
https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-process=image%2Fresize%2Cp_10&x-oss-date=20241115T095058Z&x-oss-expires=3600&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI***********1Uuu%2F20241115%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=6e7*************************1eb79d96
In this way, the file owner can securely authorize third-party access to the file without exposing the key.
Scenarios
-
Short-term file sharing: When a third party requests to upload or download a specified file, the backend generates a presigned URL with a validity period and returns it to the frontend. The third party can use the URL to upload or download the file within the validity period, ensuring data security.
-
Flexible access: The file owner can share the presigned URL through email or chat tools. After obtaining the URL, the third party can paste it into the browser address bar to download the file.