All Products
Search
Document Center

Object Storage Service:Use a presigned URL to upload a file with OSS SDK for .NET

Last Updated:Apr 03, 2025

By default, the access control list (ACL) of an Object Storage Service (OSS) object in a bucket is private. Only the object owner has the permissions to upload an object to the bucket. You can use OSS SDK for .NET to generate a presigned URL, which you can then share with a user to allow them to upload an object. When you generate the presigned URL, you can specify its validity period to limit the time during which the user can upload the object. During the validity period of the presigned URL, the user can use the URL to upload an object to the bucket multiple times. Uploading the object multiple times may cause data overwriting. After the validity period of the presigned URL ends, the user can no longer use the presigned URL to upload an object. To prolong access for the user, you can regenerate a presinged URL.

Usage 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 the access credentials, see Configure access credentials.

  • To generate a presigned URL for file uploads, you must have the oss:PutObject permission. For more information, see Attach a custom policy to a RAM user.

    Note

    The SDK uses a specific algorithm and the key information stored in the local computer to calculate a signature, and adds the signature to the URL to ensure the validity and security of the URL. Signature calculation and URL construction are performed on the client side and do not involve sending requests to the server over the network. Therefore, you do not have to be granted specific permissions to generate a presigned URL. However, to allow third-party users to perform intended operations on a resource, make sure that the identity principal that generates the presigned URL has the corresponding permissions to perform the operations.

  • In this topic, the signature algorithm V4 is used to generate presigned URLs with a validity period of up to 7 days. For more information, see (Recommended) Include a V4 signature in a URL.

  • Presigned URLs generated by using the following sample code may contain plus signs (+). In this case, replace plus signs + with %2B to ensure that the presigned URLs are accessible.

  • To generate a presigned URL that uses the HTTPS scheme, set the protocol in the endpoint to HTTPS.

Process

The following figure shows how to use a presigned URL that allows HTTP PUT requests to upload an object to OSS.

image

Sample code

The following sample code shows how to generate and use a presigned URL for data uploads to OSS. For the complete sample code, visit GitHub.

Generate and use a presigned URL for data uploads

  1. Generate a presigned URL.

    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.";
    // 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. 
    const string region = "cn-hangzhou";
    
    // Create a ClientConfiguration instance and modify the default parameter settings based on your requirements. 
    var conf = new ClientConfiguration();
    
    // Specify the V4 signature algorithm. 
    conf.SignatureVersion = SignatureVersion.V4;
    
    // Create an OSSClient instance. 
    var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
    conf.SetRegion(region);
    try
    {
        // Generate a presigned URL. 
        var generatePresignedUriRequest = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Put)
        {
            // Set the validity period of the presigned 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);
    }
  2. Use the presigned URL to upload 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;
    }

FAQ

When I use a presigned URL to upload a local file, will the file upload fail if the presigned URL expires during the upload?

No, the file upload will not fail, even if the presigned URL expires during the upload process.

A presigned URL can be used within its validity period, which is determined by the shorter duration of the token validity and the signature validity.

Can I generate a presigned URL that supports the HTTP POST method?

No, you cannot generate a presigned URL that supports the HTTP POST method.

You can generate only presigned URLs that support HTTP PUT and GET methods. If you want to upload an object by using the HTTP POST method, you must create a POST request. For more information, see PostObject.