All Products
Search
Document Center

Object Storage Service:Download an object using a presigned URL

Last Updated:Apr 11, 2025

By default, the access control list (ACL) of an object in an Object Storage Service (OSS) bucket is private. Only the object owner has the permissions to access the object. You can use OSS SDK for Python to generate a presigned URL that allows HTTP GET requests and has a validity period and share the presigned URL with a user to temporarily allow the user to download the object. Within the validity period, the user can repeatedly download the object. After the validity period ends, the user must obtain a new presigned URL.

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.

  • In this topic, access credentials are obtained from environment variables. For more information about how to configure access credentials, see Configure Access Credentials.

  • In this topic, an OSSClient instance is created by using an OSS endpoint. If you want to create an OSSClient instance by using custom domain names or Security Token Service (STS), see Initialization.

  • No specific permissions are required for the generation of presigned URLs. However, a pre-signed URL allows third-party users to download the object only if the creator of the URL has the oss:GetObject permission. For more information, see Attach a custom policy to a RAM user.

  • In this topic, V4 presignedURLs that have a validity period of seven days are used. For more information, see (Recommended) Include a V4 signature in a URL.

Process

The following figure shows how to use a presigned URL to download an object.

image

Sample code

  1. The following code provides an example of how to generate a presigned URL that allows HTTP GET requests:

    # -*- 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 for 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 ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4.
    region = "cn-hangzhou"
    
    # Specify the name of your bucket.
    bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
    
    # Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt.
    object_name = 'exampledir/exampleobject.txt'
    
    # Generate a presigned URL that is used to download the object. In this example, the validity period of the URL is 600 seconds.
    # By default, OSS identifies forward slashes (/) in the full path of an object as escape characters in the signing process. Therefore, the presigned 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, and the presigned URL can be directly used.
    url = bucket.sign_url('GET', object_name, 600, slash_safe=True)
    print('Presigned URL:', url)
  2. The following code provides an example of how to use the presigned URL that allows HTTP GET requests to download an object:

    curl

    curl -SO "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"

    Java

    import java.io.BufferedInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class Demo {
        public static void main(String[] args) {
            // Specify the presigned URL that allows HTTP GET requests. 
            String fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************";
            // Specify the path in which the downloaded object is stored, including the object name and extension. 
            String savePath = "C:/downloads/myfile.txt";
    
            try {
                downloadFile(fileURL, savePath);
                System.out.println("Download completed!");
            } catch (IOException e) {
                System.err.println("Error during download: " + e.getMessage());
            }
        }
    
        private static void downloadFile(String fileURL, String savePath) throws IOException {
            URL url = new URL(fileURL);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            httpConn.setRequestMethod("GET");
    
            // Specify the response code.
            int responseCode = httpConn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // Configure the input stream.
                InputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
                // Configure the output stream.
                FileOutputStream outputStream = new FileOutputStream(savePath);
    
                byte[] buffer=new byte[4096]; // Specify the size of the buffer.
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
    
                outputStream.close();
                inputStream.close();
            } else {
                System.out.println("No file to download. Server replied HTTP code: " + responseCode);
            }
            httpConn.disconnect();
        }
    }

    Node.js

    const https = require('https');
    const fs = require('fs');
    
    const fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************";
    const savePath = "C:/downloads/myfile.txt";
    
    https.get(fileURL, (response) => {
        if (response.statusCode === 200) {
            const fileStream = fs.createWriteStream(savePath);
            response.pipe(fileStream);
            
            fileStream.on('finish', () => {
                fileStream.close();
                console.log("Download completed!");
            });
        } else {
            console.error(`Download failed. Server responded with code: ${response.statusCode}`);
        }
    }).on('error', (err) => {
        console.error("Error during download:", err.message);
    });

    Python

    import requests
    
    file_url = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"
    save_path = "C:/downloads/myfile.txt"
    
    try:
        response = requests.get(file_url, stream=True)
        if response.status_code == 200:
            with open(save_path, 'wb') as f:
                for chunk in response.iter_content(4096):
                    f.write(chunk)
            print("Download completed!")
        else:
            print(f"No file to download. Server replied HTTP code: {response.status_code}")
    except Exception as e:
        print("Error during download:", e)

    Go

    package main
    
    import (
        "io"
        "net/http"
        "os"
    )
    
    func main() {
        fileURL := "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"
        savePath := "C:/downloads/myfile.txt"
    
        response, err := http.Get(fileURL)
        if err != nil {
            panic(err)
        }
        defer response.Body.Close()
    
        if response.StatusCode == http.StatusOK {
            outFile, err := os.Create(savePath)
            if err != nil {
                panic(err)
            }
            defer outFile.Close()
    
            _, err = io.Copy(outFile, response.Body)
            if err != nil {
                panic(err)
            }
            println("Download completed!")
        } else {
            println("No file to download. Server replied HTTP code:", response.StatusCode)
        }
    }

    JavaScript

    const fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************";
    const savePath = "C:/downloads/myfile.txt"; // Specify the name of the downloaded object.
    
    fetch(fileURL)
        .then(response => {
            if (!response.ok) {
                throw new Error(`Server replied HTTP code: ${response.status}`);
            }
            return response.blob(); // Change the type of the response to blob.
        })
        .then(blob => {
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download=savePath; // Specify the name of the downloaded object.
            document.body.appendChild(link); // This step ensures that the link exists in the document.
            link.click(); // Click the link to simulate the download.
            link.remove(); // Remove the link after the object is downloaded.
            console.log("Download completed!");
        })
        .catch(error => {
            console.error("Error during download:", error);
        });

    Android-Java

    import android.os.AsyncTask;
    import android.os.Environment;
    import java.io.BufferedInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class DownloadTask extends AsyncTask<String, String, String> {
        @Override
        protected String doInBackground(String... params) {
            String fileURL = params[0];
            String savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/myfile.txt"; // Specify the path in which you want to store the downloaded object.
            try {
                URL url = new URL(fileURL);
                HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
                httpConn.setRequestMethod("GET");
                int responseCode = httpConn.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    InputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
                    FileOutputStream outputStream = new FileOutputStream(savePath);
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    outputStream.close();
                    inputStream.close();
                    return "Download completed!";
                } else {
                    return "No file to download. Server replied HTTP code: " + responseCode;
                }
            } catch (Exception e) {
                return "Error during download: " + e.getMessage();
            }
        }
    }

    Objective-C

    #import <Foundation/Foundation.h>
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // Specify the presigned URL and the path in which you want to store the object.
            NSString *fileURL = @"https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************";
            NSString *savePath = @"/Users/your_username/Desktop/myfile.txt"; // Replace your_username with your actual username.
            
            // Create a URL object.
            NSURL *url = [NSURL URLWithString:fileURL];
            
            // Create an object download task.
            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                // Handle errors.
                if (error) {
                    NSLog(@"Error during download: %@", error.localizedDescription);
                    return;
                }
                
                // Check the data of the object.
                if (!data) {
                    NSLog(@"No data received.");
                    return;
                }
                
                // Save the object.
                NSError *writeError = nil;
                BOOL success = [data writeToURL:[NSURL fileURLWithPath:savePath] options:NSDataWritingAtomic error:&writeError];
                if (success) {
                    NSLog(@"Download completed!");
                } else {
                    NSLog(@"Error saving file: %@", writeError.localizedDescription);
                }
            }];
            
            // Start the object download task.
            [task resume];
            
            // Continue to run the main thread to complete the asynchronous request.
            [[NSRunLoop currentRunLoop] run];
        }
        return 0;
    }

Other scenarios

Generate a presigned URL that allows the HTTP GET requests for a specific version of an object

The following sample code provides an example of how to generate a presigned URL that allows HTTP GET requests for a specific version of an object:

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
import requests

# 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 for 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 ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4.
region = "cn-hangzhou"

# Specify the name of your bucket.
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)

# Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt.
object_name = 'exampledir/exampleobject.txt'

# Specify request headers.
headers = dict()
# Specify the version ID of the object.
headers["versionId"] = "CAEQARiBgID8rumR2hYiIGUyOTAyZGY2MzU5MjQ5ZjlhYzQzZjNlYTAyZDE3****"

# Generate a presigned URL and set the validity period of the presigned URL to 600 seconds.
# By default, OSS identifies forward slashes (/) in the full path of an object as escape characters in the signing process. Therefore, the presigned 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, and the presigned URL can be directly used.
url = bucket.sign_url('PUT', object_name, 600, slash_safe=True, headers=headers)
print('Presigned URL:', url)

Use a presigned URL that contains specific request headers to download an object

If you specify request headers when you generate a presigned URL that allows HTTP GET requests, make sure that the request headers are included in the GET request initiated by using the presigned URL. This prevents request failures and signature errors.

  1. Generate a presigned URL that contains specific request headers and allows HTTP GET requests.

    # -*- 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 for 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 ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4.
    region = "cn-hangzhou"
    
    # Specify the name of your bucket.
    bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
    
    # Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt.
    object_name = 'exampledir/exampleobject.txt'
    
    # Specify request headers.
    headers = dict()
    # Specify the Content-Type header.
    headers['Content-Type'] = 'text/plain; charset=utf8'
    
    # Specify HTTP query parameters.
    params = dict()
    # Configure single-connection bandwidth throttling. Unit: bit/s. In this example, the throttling threshold is set to 100 KB/s.
    # params['x-oss-traffic-limit'] = str(100 * 1024 * 8)
    # Specify the IP address or CIDR block.
    # params['x-oss-ac-source-ip'] = "127.0.0.1"
    # Specify the number of the digit 1 in the subnet mask.
    # params['x-oss-ac-subnet-mask'] = "32"
    # Specify the ID of the VPC.
    # params['x-oss-ac-vpc-id'] = "vpc-t4nlw426y44rd3iq4xxxx"
    # Specify whether to allow request forwarding.
    # params['x-oss-ac-forward-allow'] = "true"
    
    # Generate a presigned URL that is used to download the object. In this example, the validity period of the URL is 600 seconds.
    # By default, OSS identifies forward slashes (/) in the full path of an object as escape characters in the signing process. Therefore, the presigned 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, and the presigned URL can be directly used.
    url = bucket.sign_url('GET', object_name, 600, slash_safe=True, headers=headers, params=params)
    print('Presigned URL:', url)
  2. Use the presigned URL and specify the request headers in the request to download the object.

    curl -X GET "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241113T093321Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************&x-oss-signature=f1746f121783eed5dab2d665da95fbca08505263e27476a46f88dbe3702af8a9***************************************" \
    -H "Content-Type: text/plain" \
    -o "myfile.txt"
    import requests
    
    def download_file(signed_url, file_path, headers=None, metadata=None):
        """
        Use the presigned URL to download the object.
    
        :param signed_url: presigned URL
        :param file_path: full path of the object to download
        :param headers: request headers. This parameter is optional.
        :param metadata: user metadata. This parameter is optional.
        :return: None
        """
        if not headers:
            headers = {}
    
        try:
            response = requests.get(signed_url, headers=headers, stream=True)
            print(f"Download status code: {response.status_code}")
    
            if response.status_code == 200:
                with open(file_path, 'wb') as file:
                    for chunk in response.iter_content(chunk_size=8192):
                        if chunk:  # filter out keep-alive new chunks
                            file.write(chunk)
                print("The object is downloaded")
            else:
                print("Download failed")
                print(response.text)
        except Exception as e:
            print(f"An error occurred: {e}")
    
    if __name__ == "__main__":
        # Replace <signedUrl> with the generated presigned URL.
        signed_url = "<signedUrl>"
        file_path = "/Users/yourLocalPath>/Downloads/downloadedFile.txt" // Specify the local path in which the object is stored.  
    
        headers = {
            "Content-Type": "text/plain; charset=utf-8",
            # Other required headers
        }
    
        download_file(signed_url, file_path, headers=headers)

Generate a presigned URL by using a custom domain name

The following code provides an example of how to generate a presigned URL using a custom domain name.

# -*- 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 ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4.
region = "cn-hangzhou"

# Specify the custom domain name. Example: static.example.com.
endpoint = 'http://static.example.com'

# Specify the name of your bucket.
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region, is_cname=True)


# Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt.
object_name = 'exampledir/exampleobject.txt'

# Generate a presigned URL that is used to download the object. In this example, the validity period of the URL is 600 seconds.
# By default, OSS identifies forward slashes (/) in the full path of an object as escape characters in the signing process. Therefore, the presigned 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, and the presigned URL can be directly used.
url = bucket.sign_url('GET', object_name, 600, slash_safe=True, params=params)
print('Presigned URL:', url)