All Products
Search
Document Center

Object Storage Service:Upload files using presigned URLs

Last Updated:Feb 25, 2025

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.

    Note

    When 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:

image

Detailed steps

Step 1: The bucket owner generates a PUT method pre-signed URL

Note

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(&region, "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

To upload files in sharding mode by using presigned URLs, you need to configure the shard size and generate a presigned URL for each shard. The following sample code provides an example:

Java

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.common.utils.CRC64;
import com.aliyun.oss.model.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.Date;

public class MultipartUrl {
    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 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 = "D:\\localpath\\examplefile.txt";
        // Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour. 
        long expireTime = 3600*1000L;
        // 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();

        // Create an InitiateMultipartUploadRequest object. 
        InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName, objectName);

        // Initiate the multipart upload task. 
        InitiateMultipartUploadResult upResult = ossClient.initiateMultipartUpload(initRequest);
        // Obtain the upload ID. The upload ID is the unique identifier of the multipart upload task. You can use the upload ID to perform related operations, such as canceling and querying the multipart upload task. 
        String uploadId = upResult.getUploadId();

        // partETags is a set of PartETags. A PartETag consists of the part number and ETag of a part. 
        List<PartETag> partETags =  new ArrayList<PartETag>();
        // Specify the part size, which is used to calculate the number of parts of the object. Unit: bytes. 
        long partSize = 1 * 100 * 1024L;   // In this example, the part size is set to 100 KB. 

        // 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. 
        File sampleFile = new File(pathName);
        long fileLength = sampleFile.length();
        // If you want to upload the local file as only one part, set the part size to the local file size. 
        // long fileLength = sampleFile.length();
        int partCount = (int) (fileLength / partSize);
        if (fileLength % partSize != 0) {
            partCount++;
        }

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


        // Traverse all parts to obtain all signed URLs and upload the parts. 
        // You can also obtain the signed URLs of all parts at a time and then upload the parts. The following sample code provides an example on how to obtain a single signed URL and use the signed URL to upload a part: 
        for (int i = 0; i < partCount; i++) {
            long startPos = i * partSize;
            long curPartSize = (i + 1 == partCount) ?  (fileLength - startPos) : partSize;

            /*// Configure MD5 verification. You can perform MD5 verification only for a single part.
            FileInputStream inStream = new FileInputStream(pathName);
            // Skip the parts that are uploaded. 
            inStream.skip(startPos);
            BoundedInputStream entity = new BoundedInputStream(inStream, partSize);
            String md5 = BinaryUtil.toBase64String(DigestUtils.md5(entity));
            headers.put("Content-MD5", md5);*/

            String signUrl = getSignUrl(ossClient, bucketName, objectName, HttpMethod.PUT, expireTime, i + 1, uploadId, headers);

            // Use the signed URL to upload the part. In this example, HttpClients is used. 
            putObjectWithHttp(signUrl, pathName, startPos, curPartSize, headers);
        }

        // If the system for part upload is different from the system for part combination, you must list the parts before you can combine the parts into a complete object. 
        // List the uploaded parts. 
        ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, objectName, uploadId);
        PartListing partListing = ossClient.listParts(listPartsRequest);

        // Traverse the parts and populate partETags. 
        for (PartSummary part : partListing.getParts()) {
            PartETag partETag = new PartETag(part.getPartNumber(), part.getETag());
            partETags.add(partETag);
        }

        // Combine the parts into a complete object. 
        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
        // String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5("aaa".getBytes()));
        // Specify that an existing object that has the same name is not overwritten. 
        // completeMultipartUploadRequest.addHeader("x-oss-forbid-overwrite", "true");

        // Complete the multipart upload task. 
        CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
        System.out.println("Parts are combined. The multipart upload task is complete.");


        // Check whether the uploaded file is complete.
        CRC64 crc = new CRC64();
        InputStream inStream = new FileInputStream(pathName);
        byte[] bytes = new byte[1024];
        int cnt;
        while ((cnt = inStream.read(bytes)) != -1) {
            crc.update(bytes, 0, cnt);
        }

        if(crc.getValue() == completeMultipartUploadResult.getServerCRC()){
            System.out.println("The uploaded file is complete");
        } else {
            System.out.println("The uploaded file is incomplete. Handle the exception");
        }
    }

    public static void putObjectWithHttp(String signedUrl, String pathName, long startPos, long partSize, Map<String, String> headers) throws IOException {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            HttpPut put = new HttpPut(signedUrl);

            FileInputStream inStream = new FileInputStream(pathName);
            // Skip the parts that are uploaded. 
            inStream.skip(startPos);
            InputStreamEntity entity = new InputStreamEntity(inStream, partSize);
            BufferedHttpEntity byteArrayEntity = new BufferedHttpEntity(entity);
            put.setEntity(byteArrayEntity);

            // If you specify headers, such as the user metadata and storage class headers, when a signed URL is generated, these headers must be sent to the server when the signed URL is used to upload the local file. If the headers that are sent to the server for the signature calculation are different from the headers specified when the signed URL is generated, a signature error is reported. 
            for(Map.Entry header: headers.entrySet()){
                put.addHeader(header.getKey().toString(),header.getValue().toString());
            }

            // Set the number of retries when a request error occurs to 3. The following sample code is used as an example to describe how to specify the number of retries when a request error occurs. Specify the number of retries when a request error occurs based on your business requirements.
            httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)).build();

            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 {
            if(response != null){
                response.close();
            }
            if(httpClient != null){
                httpClient.close();
            }
        }
    }

    public static String getSignUrl(OSS ossClient, String bucketName, String objectName, HttpMethod method, long expireTime, int partNum, String uploadId, Map<String, String> headers){
        // Specify the validity period of the signed URLs. Unit: milliseconds. 
        Date expiration = new Date(new Date().getTime() + expireTime);

        // Generate the signed URLs. 
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, method);
        // Specify the validity period of the signed URLs. 
        request.setExpiration(expiration);

        // Add headers to the request. 
        request.setHeaders(headers);

        request.addQueryParameter("partNumber", String.valueOf(partNum));

        request.addQueryParameter("uploadId", uploadId);


        // Generate the signed URLs that allow HTTP requests. 
        URL signedUrl = ossClient.generatePresignedUrl(request);
        // Display the signed URLs. 
        System.out.println("signed url: " + signedUrl);
        return signedUrl.toString();
    }
}

Go

package main

import (
	"bytes"
	"context"
	"flag"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

var (
	region     string                     // Specify the region.
	bucketName string                     // Specify the name of the bucket.
	objectName string                     // Specify the name of the object.
	length     = int64(5000 * 1024)       // Specify the total length of the file. Unit: bytes.
	partSize   = int64(200 * 1024)        // Specify the size of each part. Unit: bytes.
	partsNum   = int(length/partSize + 1) // Specify the number of parts.
	data       = make([]byte, length)     // Simulate the data to upload.
)

// Initialize command line parameters.
func init() {
	flag.StringVar(&region, "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 required parameters are specified.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// Configure the OSSClient instance.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// Create the OSSClient instance.
	client := oss.NewClient(cfg)

	// Initialize the multipart upload task.
	initResult, err := client.InitiateMultipartUpload(context.TODO(), &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	})
	if err != nil {
		log.Fatalf("failed InitiateMultipartUpload %v", err)
	}

	// Traverse all parts to obtain all signed URLs and upload the parts.
	for i := 0; i < partsNum; i++ {
		start := int64(i) * partSize
		end := start + partSize
		if end > length {
			end = length
		}
		signedResult, err := client.Presign(context.TODO(), &oss.UploadPartRequest{
			Bucket:     oss.Ptr(bucketName),
			Key:        oss.Ptr(objectName),
			PartNumber: int32(i + 1),
			Body:       bytes.NewReader(data[start:end]),
			UploadId:   initResult.UploadId,
		}, oss.PresignExpiration(time.Now().Add(1*time. hour)) // Generate signed URLs that have a validity period of 1 hour.
		if err != nil {
			log.Fatalf("failed to generate presigned URL %v", err)
		}
		fmt.Printf("signed url:%#v\n", signedResult.URL) // Display the generated signed URLs.

		// Create an HTTP request and upload parts.
		req, err := http.NewRequest(signedResult.Method, signedResult.URL, bytes.NewReader(data[start:end]))
		if err != nil {
			log.Fatalf("failed to create HTTP request %v", err)
		}

		c := &http. Client{} // Create an HTTP client.
		_, err = c.Do(req)
		if err != nil {
			log.Fatalf("failed to upload part by signed URL %v", err)
		}
	}

	// List uploaded parts.
	partsResult, err := client.ListParts(context.TODO(), &oss.ListPartsRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		UploadId: initResult.UploadId,
	})
	if err != nil {
		log.Fatalf("failed to list parts %v", err)
	}

	// Collect information about the uploaded parts.
	var parts []oss.UploadPart
	for _, p := range partsResult.Parts {
		parts = append(parts, oss.UploadPart{PartNumber: p.PartNumber, ETag: p.ETag})
	}

	// Complete the multipart upload task.
	result, err := client.CompleteMultipartUpload(context.TODO(), &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		UploadId: initResult.UploadId,
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts,
		},
	})
	if err != nil {
		log.Fatalf("failed to complete multipart upload %v", err)
	}

	// Display the result of the multipart upload task.
	log.Printf("complete multipart upload result:%#v\n", result)
}

Define upload policies by using presigned URLs (with headers)

By specifying header parameters, you can define upload policies, such as specifying the storage class of the object or setting the access control list of the object. If request headers are specified when you generate a presigned URL, make sure that the request headers are included when you use the presigned URL to avoid inconsistencies, which may cause request failures and signature errors. For more information about the headers that can be specified, see PutObject. You can also specify custom metadata for file management. For more information about how to specify custom metadata, see Manage file metadata.

For example, if the Content-Type and x-oss-storage-class headers are specified when you generate a presigned URL, you must also specify the Content-Type and x-oss-storage-class headers when you upload the object by using the presigned URL. Otherwise, a 403 error is returned.

  1. The file owner generates a presigned URL with the PUT method.

Java

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 = "zy-test1009";
        // 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 = "exampleobject1.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();

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

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

        URL signedUrl = null;
        try {
            // Specify the validity period of the signed URL. Unit: milliseconds. 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);

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

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

        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        }
    }
}       

Go

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"
)

// Define 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.
)

// Use the init function to initialize command line parameters
func init() {
	flag.StringVar(&region, "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 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 presigned 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/plain; charset=utf-8"),                    // Make sure that the ContentType specified when the signed URL is generated is consistent with the ContentType specified when the URL is used
		Metadata:    map[string]string{"key1": "value1", "key2": "value2"}, // Make sure that the Metadata specified when the signed URL is generated is consistent with the Metadata specified when the URL is used
	},
		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

# -*- 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'

# Specify request headers. 
headers = dict()
# Specify the Content-Type header. 
headers['Content-Type'] = 'text/plain'
# Specify the storage class of the object. 
headers["x-oss-storage-class"] = "Standard"

# Specify user metadata.
metadata = {'key1': 'value1', 'key2': 'value2'}
# Add the x-oss-meta- prefix to the metadata items.
for key, value in metadata.items():
    headers[f'x-oss-meta-{key}'] = value

# 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, headers=headers)
print ('Signed URL:', url)
  1. Others upload files using the presigned URL with the PUT method.

curl -X PUT \
     -H "Content-Type: text/plain; charset=utf8" \
     -H "x-oss-meta-key1: value1" \
     -H "x-oss-meta-key2: value2" \
     -T "C:\\Users\\demo.txt" \
     "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**********"
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 signed URL.
        URL signedUrl = new URL("<signedUrl>");

        // Specify the full path of the local file. If the path of the local file is not specified, the local file is uploaded from the path of the project to which the sample program belongs.
        String pathName = "C:\\Users\\demo.txt";

        // Specify request headers. Make sure that the values of the request headers are the same as that of the request headers when the signed URL is generated.
        Map<String, String> headers = new HashMap<String, String>();
        /*// Specify the storage class of the object.
        headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
        // Specify the content type.
        headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/

        // Specify user metadata. Make sure that the user metadata is the same as the user metadata when the signed URL is generated.
        Map<String, String> userMetadata = new HashMap<String, String>();
        /*userMetadata.put("key1","value1");
        userMetadata.put("key2","value2");*/

        try {
            HttpPut put = new HttpPut(signedUrl.toString());
            System.out.println(put);
            HttpEntity entity = new FileEntity(new File(pathName));
            put.setEntity(entity);
            // If headers are specified when you generate a presigned URL, such as user metadata and storage class, make sure that the headers are included in the request when you upload the object by using the presigned URL. If the headers that are sent to the server for the signature calculation are different from the headers specified when the signed URL is generated, a signature error is reported.
            for(Map.Entry header: headers.entrySet()){
                put.addHeader(header.getKey().toString(),header.getValue().toString());
            }
            for(Map.Entry meta: userMetadata.entrySet()){
                // If userMeta is used, the x-oss-meta- prefix is added to userMeta. When you use other methods to generate a presigned URL to upload an object, you must also add the x-oss-meta- prefix to userMeta.
                put.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString());
            }

            httpClient = HttpClients.createDefault();

            response = httpClient.execute(put);

            System.out.println("Upload status code:"+response.getStatusLine().getStatusCode());
            if(response.getStatusLine().getStatusCode() == 200){
                System.out.println("Upload successfully using the network library");
            }
            System.out.println(response.toString());
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            response.close();
            httpClient.close();
        }
    }
}       
import requests
from requests.auth import HTTPBasicAuth
import os

def upload_file(signed_url, file_path, headers=None, metadata=None):
    """
    Use the pre-signed URL to upload an object to OSS.

    :param signed_url: Specify the pre-signed URL.
    :param file_path: Specify the full path of the local file that you want to upload.
    :param headers: Optional. Specify the request headers.
    :param metadata: Optional. Specify the user metadata.
    :return: None
    """
    if not headers:
        headers = {}
    if not metadata:
        metadata = {}

    # Update the request headers and specify the metadata prefix
    for key, value in metadata.items():
        headers[f'x-oss-meta-{key}'] = value

    try:
        with open(file_path, 'rb') as file:
            response = requests.put(signed_url, data=file, headers=headers)
            print(f"Upload status code:{response.status_code}")
            if response.status_code == 200:
                print("Upload successfully using the network library")
            else:
                print("Upload failed")
            print(response.text)
    except Exception as e:
        print(f"An error occurred:{e}")

if __name__ == "__main__":
    // Replace <signedUrl> with the signed URL.
    signed_url = "<signedUrl>"
   
    // Specify the full path of the local file. If you do not specify the full path, the local file is uploaded from the directory in which the script is stored.
    file_path = "C:\\Users\\demo.txt"

    // Specify request headers. Make sure that the values of the request headers are the same as that of the request headers when the signed URL is generated.
    headers = {
         "Content-Type": "text/plain; charset=utf8",
         "x-oss-storage-class": "Standard"
    }

    // Specify user metadata. Make sure that the user metadata is the same as the user metadata when the signed URL is generated.
    metadata = {
         "key1": "value1",
         "key2": "value2"
    }

    upload_file(signed_url, file_path, headers, metadata)
const fs = require('fs');
const axios = require('axios');

async function uploadFile(signedUrl, filePath, headers = {}, metadata = {}) {
    try {
        // Update the request headers and specify the metadata prefix
        for (const [key, value] of Object.entries(metadata)) {
            headers[`x-oss-meta-${key}`] = value;
        }

        // Read the file stream
        const fileStream = fs.createReadStream(filePath);

        // Send the PUT request
        const response = await axios.put(signedUrl, fileStream, {
            headers: headers
        });

        console.log(`Upload status code:${response.status}`);
        if (response.status === 200) {
            console.log("Upload successfully using the network library");
        } else {
            console.log("Upload failed");
        }
        console.log(response.data);
    } catch (error) {
        console.error(`An error occurred:${error.message}`);
    }
}

// Specify the main function
(async () => {
    // Replace <signedUrl> with the signed URL.
    const signedUrl = "<signedUrl>";

    // Specify the full path of the local file. If you do not specify the full path, the local file is uploaded from the directory in which the script is stored.
    const filePath = "C:\\Users\\demo.txt";

    // Specify request headers. Make sure that the values of the request headers are the same as that of the request headers when the signed URL is generated.
    const headers = {
        // "Content-Type": "text/txt",
        // "x-oss-storage-class": "Standard"
    };

    // Specify user metadata. Make sure that the user metadata is the same as the user metadata when the signed URL is generated.
    const metadata = {
        // "key1": "value1",
        // "key2": "value2"
    };

    await uploadFile(signedUrl, filePath, headers, metadata);
})();
<!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>"; 

        // Specify the content type, storage class, and metadata
        const contentType = 'text/plain';

        const storageClass = 'Standard';

        const metadata = {
            'x-oss-meta-key1': 'value1',
            'x-oss-meta-key2': 'value2'
        };

        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 headers = {
                    'Content-Type': contentType,
                    'x-oss-storage-class':storageClass,
                    ...metadata
                };
                
                const response = await fetch(presignedUrl, {
                    method: 'PUT',
                    headers: headers,
                    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>
#include <iostream>
#include <fstream>
#include <curl/curl.h>
#include <map>
#include <string>

// Specify the callback function that is used to process the HTTP response
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
    size_t totalSize = size * nmemb;
    output->append((char*)contents, totalSize);
    return totalSize;
}

void uploadFile(const std::string& signedUrl, const std::string& filePath, const std::map<std::string, std::string>& headers, const std::map<std::string, std::string>& metadata) {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    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 local file: " << filePath << std::endl;
            return;
        }

        // Specify the size of the local file
        fseek(file, 0, SEEK_END);
        long fileSize = ftell(file);
        rewind(file);

        // Configure a callback when you read the object
        curl_easy_setopt(curl, CURLOPT_READDATA, file);
        curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);

        // Specify request headers
        struct curl_slist* chunk = nullptr;
        for (const auto& header : headers) {
            std::string headerStr = header.first + ": " + header.second;
            chunk = curl_slist_append(chunk, headerStr.c_str());
        }
        for (const auto& meta : metadata) {
            std::string metaStr = "x-oss-meta-" + meta.first + ": " + meta.second;
            chunk = curl_slist_append(chunk, metaStr.c_str());
        }
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);

        // Specify the callback function that is used to process the response
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        // Execute the request
        res = curl_easy_perform(curl);

        // Check the response
        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        } else {
            long responseCode;
            curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
            std::cout << "Upload status code: " << responseCode << std::endl;
            if (responseCode == 200) {
                std::cout << "Upload successfully using the network library" << std::endl;
            } else {
                std::cout << "Upload failed" << std::endl;
            }
            std::cout << readBuffer << std::endl;
        }

        // Clean up
        fclose(file);
        curl_slist_free_all(chunk);
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
}

int main() {
    // Replace <signedUrl> with the signed URL.
    std::string signedUrl = "<signedUrl>";

    // Specify the full path of the local file. If the path of the local file is not specified, the local file is uploaded from the path of the project to which the sample program belongs.
    std::string filePath = "C:\\Users\\demo.txt";

    // Specify request headers. Make sure that the values of the request headers are the same as that of the request headers when the signed URL is generated.
    std::map<std::string, std::string> headers = {
        // {"Content-Type", "text/txt"},
        // {"x-oss-storage-class", "Standard"}
    };

    // Specify user metadata. Make sure that the user metadata is the same as the user metadata when the signed URL is generated.
    std::map<std::string, std::string> metadata = {
        // {"key1", "value1"},
        // {"key2", "value2"}
    };

    uploadFile(signedUrl, filePath, headers, metadata);

    return 0;
}
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

func uploadFile(signedUrl string, filePath string, headers map[string]string, metadata map[string]string) error {
	// Open the local file
	file, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	// Read the file content
	fileBytes, err := ioutil.ReadAll(file)
	if err != nil {
		return err
	}

	// Create a request
	req, err := http.NewRequest("PUT", signedUrl, bytes.NewBuffer(fileBytes))
	if err != nil {
		return err
	}

	// Specify request headers
	for key, value := range headers {
		req.Header.Set(key, value)
	}

	// Specify user metadata
	for key, value := range metadata {
		req.Header.Set(fmt.Sprintf("x-oss-meta-%s", key), value)
	}

	// Send the request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Process the response
	fmt.Printf("Upload status code: %d\n", resp.StatusCode)
	if resp.StatusCode == 200 {
		fmt.Println("Upload successfully using the network library")
	} else {
		fmt.Println("Upload failed")
	}
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body))

	return nil
}

func main() {
	// Replace <signedUrl> with the signed URL.
	signedUrl := "<signedUrl>"

	// Specify the full path of the local file. If the path of the local file is not specified, the local file is uploaded from the path of the project to which the sample program belongs.
	filePath := "C:\\Users\\demo.txt"

	// Specify request headers. Make sure that the values of the request headers are the same as that of the request headers when the signed URL is generated.
	headers := map[string]string{
		// "Content-Type": "text/txt",
		// "x-oss-storage-class": "Standard",
	}

	// Specify user metadata. Make sure that the user metadata is the same as the user metadata when the signed URL is generated.
	metadata := map[string]string{
		// "key1": "value1",
		// "key2": "value2",
	}

	err := uploadFile(signedUrl, filePath, headers, metadata)
	if err != nil {
		fmt.Printf("An error occurred:%v\n", err)
	}
}
import android.os.AsyncTask;
import android.util.Log;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class SignUrlUploadActivity extends AppCompatActivity {

    private static final String TAG = "SignUrlUploadActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Replace <signedUrl> with the signed URL.
        String signedUrl = "<signedUrl>";

        // Specify the full path of the local file. If the path of the local file is not specified, the local file is uploaded from the path of the project to which the sample program belongs.
        String pathName = "/storage/emulated/0/demo.txt";

        // Specify request headers. Make sure that the values of the request headers are the same as that of the request headers when the signed URL is generated.
        Map<String, String> headers = new HashMap<>();
        // headers.put("Content-Type", "text/txt");
        // headers.put("x-oss-storage-class", "Standard");

        // Specify user metadata. Make sure that the user metadata is the same as the user metadata when the signed URL is generated.
        Map<String, String> userMetadata = new HashMap<>();
        // userMetadata.put("key1", "value1");
        // userMetadata.put("key2", "value2");

        new UploadTask().execute(signedUrl, pathName, headers, userMetadata);
    }

    private class UploadTask extends AsyncTask<Object, Void, Integer> {
        @Override
        protected Integer doInBackground(Object... params) {
            String signedUrl = (String) params[0];
            String pathName = (String) params[1];
            Map<String, String> headers = (Map<String, String>) params[2];
            Map<String, String> userMetadata = (Map<String, String>) params[3];

            try {
                URL url = new URL(signedUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("PUT");
                connection.setDoOutput(true);
                connection.setUseCaches(false);

                // Specify request headers
                for (Entry<String, String> header : headers.entrySet()) {
                    connection.setRequestProperty(header.getKey(), header.getValue());
                }

                // Specify user metadata
                for (Entry<String, String> meta : userMetadata.entrySet()) {
                    connection.setRequestProperty("x-oss-meta-" + meta.getKey(), meta.getValue());
                }

                // Read the file
                File file = new File(pathName);
                FileInputStream fileInputStream = new FileInputStream(file);
                DataOutputStream dos = new DataOutputStream(connection.getOutputStream());

                byte[] buffer = new byte[1024];
                int count;
                while ((count = fileInputStream.read(buffer)) != -1) {
                    dos.write(buffer, 0, count);
                }

                fileInputStream.close();
                dos.flush();
                dos.close();

                // Obtain the response
                int responseCode = connection.getResponseCode();
                Log.d(TAG, "Upload status code:" + responseCode);
                if (responseCode == 200) {
                    Log.d(TAG, "Upload successfully using the network library");
                } else {
                    Log.d(TAG, "Upload failed");
                }

                InputStream is = connection.getInputStream();
                byte[] responseBuffer = new byte[1024];
                StringBuilder responseStringBuilder = new StringBuilder();
                while ((count = is.read(responseBuffer)) != -1) {
                    responseStringBuilder.append(new String(responseBuffer, 0, count));
                }
                Log.d(TAG, responseStringBuilder.toString());

                return responseCode;
            } catch (IOException e) {
                e.printStackTrace();
                return -1;
            }
        }

        @Override
        protected void onPostExecute(Integer result) {
            super.onPostExecute(result);
            if (result == 200) {
                Toast.makeText(SignUrlUploadActivity.this, "Object uploaded", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(SignUrlUploadActivity.this, "Upload failed", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

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.

FAQ

How can I authorize a third party to perform more operations on OSS resources, not just uploads?

In addition to presigned URLs, Alibaba Cloud also provides a more flexible temporary authorization method—STS temporary access credentials. If you want a third party to perform more OSS resource management operations, such as listing files and copying files, rather than just uploading, we recommend that you learn about and use STS temporary access credentials. For more information, see Use STS temporary access credentials to access OSS.

Can I allow only specified websites to access OSS resources and reject requests from other sources?

Yes, you can configure hotlink protection by setting a whitelist to allow only specific websites (such as your website) to access OSS resources, preventing other malicious sources from directly referencing your OSS files without going through your website. For detailed configuration steps, see Configure hotlink protection to prevent other websites from referencing OSS files.

Error: CORS error

The bucket cross-origin resource sharing (CORS) policy is not configured or is configured incorrectly. For more information, see Cross-origin settings.

Error: 405 Method Not Allowed

The request method is incorrect. When you upload an object by using a signed URL, make sure that you use the PUT request instead of the POST request.