All Products
Search
Document Center

Object Storage Service:Upload an object by using a presigned URL (Node.js SDK)

Last Updated:Nov 29, 2025

By default, objects in an Object Storage Service (OSS) bucket are private. Only the object owner has permission to upload objects. You can use the OSS software development kit (SDK) for Node.js to generate a presigned URL that allows other users to upload an object. When you generate the URL, you can set a custom expiration time. The URL can be used multiple times within its validity period. If you perform multiple uploads using the same URL, the object may be overwritten. After the URL expires, it can no longer be used. You must generate a new presigned URL to perform an upload.

Notes

  • 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.

  • This topic uses access credentials that are read from environment variables as an example. For more information about how to configure access credentials, see Configure access credentials (Node.js SDK).

  • To generate a presigned URL for an upload, you must have the oss:PutObject permission. For more information, see Grant custom policies to a RAM user.

    Note

    When you generate a presigned URL, the SDK uses the locally stored key to calculate a signature based on a specific algorithm. The SDK then appends the signature to the URL to ensure its validity and security. This calculation and URL construction process occurs on the client and does not involve network requests to the server. Therefore, the caller does not need specific permissions to generate the presigned URL. However, the identity that generates the URL must have the required permissions for the resource. This ensures that third-party users can perform the authorized operations on the resource.

  • This topic uses V4 presigned URLs as an example. The maximum validity period is seven days. For more information, see Signature V4 (Recommended).

Process

The following process describes how to upload a file using a presigned URL for a PUT request:

image

Sample code

  1. The object owner generates a presigned URL for a PUT method.

    const OSS = require("ali-oss");
    
    // Define a function to generate a signed URL.
    async function generateSignatureUrl(fileName) {
      // Obtain the presigned 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: {} // Set the request headers based on the actual request headers.
      }, fileName);
    }
    // Call the function and pass the file name.
    generateSignatureUrl('yourFileName').then(url => {
      console.log('Generated Signature URL:', url);
    }).catch(err => {
      console.error('Error generating signature URL:', err);
    });
  2. Another user uploads a file using the presigned URL for the PUT method.

    curl

    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=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"

    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 presigned URL. 
            URL signedUrl = new URL("<signedUrl>");
    
            // Specify the full path of the local file that you want to upload. 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";
    
            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("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();
            }
        }
    }       

    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 an 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 request: %w", err)
    	}
    
    	fmt.Printf("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 presigned URL. 
    	signedUrl := "<signedUrl>"
    
    	// Specify the full path of the local file that you want to upload. 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"
    
    	err := uploadFile(signedUrl, filePath)
    	if err != nil {
    		fmt.Println("An error occurred: ", err)
    	}
    }
    

    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 local file.
                response = requests.put(signed_url, data=file)
         
            print(f"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. 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. 
        file_path = "C:\\Users\\demo.txt"
    
        upload_file(signed_url, file_path)
    

    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.
                }
            });
    
            console.log(`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 presigned URL. 
        const signedUrl = '<signedUrl>';
        
        // Specify the full path of the local file that you want to upload. 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. 
        const filePath = 'C:\\Users\\demo.txt';
    
        await uploadFile(signedUrl, filePath);
    })();

    browser.js

    Important

    When uploading an object using Browser.js and a presigned URL, a 403 SignatureNotMatch error that indicates signature inconsistency may occur. This is typically caused by the browser's automatic inclusion of the Content-Type request header, which that was not specified when the presigned URL was generated. To prevent this error, ensure that the Content-Type header is specified when generating a presigned URL.

    <!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>
    
        <! -- Select File -->
        <input type="file" id="fileInput" />
        <button id="uploadButton">Upload File</button>
    
        <script>
            // Replace <signedUrl> with the presigned URL that was generated in Step 1. 
            const signedUrl = "<signedUrl>"; 
    
    
            document.getElementById('uploadButton').addEventListener('click', async () => {
                const fileInput = document.getElementById('fileInput');
                const file = fileInput.files[0];
    
                if (!file) {
                    alert('Please select a file to upload.');
                    return;
                }
    
                try {
                    await upload(file, signedUrl);
                    alert('File uploaded successfully!');
                } catch (error) {
                    console.error('Error during upload:', error);
                    alert('Upload failed: ' + error.message);
                }
            });
    
            /**
             * Upload a file to OSS.
             * @param {File} file - The file to be uploaded.
             * @param {string} presignedUrl - The presigned URL.
             */
            const upload = async (file, presignedUrl) => {
                const response = await fetch(presignedUrl, {
                    method: 'PUT',
                    body: file,  // Upload the entire file.
                });
    
                if (!response.ok) {
                    throw new Error(`Upload failed, status: ${response.status}`);
                }
    
                console.log('File uploaded successfully');
            };
        </script>
    </body>
    </html>

    C#

    using System.Net.Http.Headers;
    
    // Specify the full path of the local file that you want to upload. 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. 
    var filePath = "C:\\Users\\demo.txt";
    // Replace <signedUrl> with the presigned URL.
    var presignedUrl = "<signedUrl>";
    
    // Create an HTTP client and a local file stream.
    using var httpClient = new HttpClient(); 
    using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    using var content = new StreamContent(fileStream);
                
    // Create a PUT request.
    var request = new HttpRequestMessage(HttpMethod.Put, presignedUrl);
    request.Content = content;
    
    // Send a request.
    var response = await httpClient.SendAsync(request);
    
    // Process the response.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Uploaded! Status Code: {response.StatusCode}");
        Console.WriteLine("Response Header:");
        foreach (var header in response.Headers)
        {
            Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
        }
    }
    else
    {
        string responseContent = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"Upload Failed! Status Code: {response.StatusCode}");
        Console.WriteLine("Response content: " + responseContent);
    }

    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 presigned 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 << "Status code: " << httpCode << std::endl;
    
                if (httpCode == 200) {
                    std::cout << "The object is uploaded by using the network 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 presigned URL. 
        std::string signedUrl = "<signedUrl>";
    
        // Specify the full path of the local file that you want to upload. 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";
    
        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, "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 presigned URL. 
            String signedUrl = "<signedUrl>";
            // Specify the full path of the local file that you want to upload. 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 filePath = "C:\\Users\\demo.txt";
            activity.uploadFile(signedUrl, filePath);
        }
    }
    

Other scenarios

Generate a presigned URL that includes image processing parameters

const OSS = require("ali-oss");

const client = await new OSS({
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  stsToken: 'yourSecurityToken',
  bucket: 'yourBucket',
  region: 'yourRegion',
  // Set secure to true to use HTTPS and prevent the browser from blocking the generated download link.
  secure: true,
});


// Generate a signed URL.
const signedUrl = await client.signatureUrlV4('GET', 3600, {
  queries:{
    // Set image processing parameters.
    "x-oss-process": 'image/resize,w_200',
  }
}, 'demo.pdf');

Generate a presigned URL with a version ID

const OSS = require("ali-oss");

const client = await new OSS({
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  stsToken: 'yourSecurityToken',
  bucket: 'yourBucket',
  region: 'yourRegion',
  // Set secure to true to use HTTPS and prevent the browser from blocking the generated download link.
  secure: true,
});


// Generate a signed URL.
const signedUrl = await client.signatureUrlV4('GET', 3600, {
  queries:{
    // Specify the versionId of the object.
    "versionId":'yourVersionId'
  }
}, 'demo.pdf');

FAQ

If I use a temporary signature to upload a file and the signature expires during the upload, does the upload fail?

The upload will succeed.

The upload uses a presigned URL. The validity period is the shorter of the token's validity period and the presigned URL's validity period.

Is the POST method supported when you generate a presigned URL?

No, it is not.

Only the PUT and GET methods are supported when you generate a presigned URL. To upload an object using the POST method, you must construct a POST request. For more information, see PostObject.

References