Tous les produits
Search
Centre de documentation

Object Storage Service:Charger un objet à l'aide d'une URL pré-signée (SDK Java V1)

Dernière mise à jour :Aug 08, 2026

Par défaut, les objets stockés dans un compartiment Object Storage Service (OSS) sont privés. Seul le propriétaire de l'objet dispose des autorisations nécessaires pour effectuer des chargements. Vous pouvez utiliser le SDK OSS pour Java afin de générer une URL pré-signée permettant à d'autres utilisateurs de charger un objet. Lors de la génération de cette URL, vous avez la possibilité de spécifier une durée d'expiration pour limiter sa validité. L'URL peut être utilisée plusieurs fois avant son expiration. Si plusieurs opérations de chargement sont effectuées, l'objet risque d'être écrasé. Une fois l'URL expirée, elle ne peut plus servir aux chargements et vous devez en générer une nouvelle.

Remarques d'utilisation

  • Cette rubrique utilise le point de terminaison public de la région Chine (Hangzhou). Pour accéder à OSS depuis d'autres services Alibaba Cloud situés dans la même région, privilégiez un point de terminaison interne. Pour obtenir la liste détaillée des régions et des points de terminaison pris en charge, consultez Régions et points de terminaison.

  • Dans cet exemple, les identifiants d'accès sont récupérés depuis des variables d'environnement. Pour plus d'informations, reportez-vous à la section Configuration des identifiants d'accès.

  • Nous illustrons ici la création d'une instance OSSClient avec un point de terminaison OSS. Pour découvrir d'autres configurations, telles que l'utilisation d'un domaine personnalisé ou l'authentification via des identifiants Security Token Service (STS), veuillez consulter la documentation relative à la Configuration du client.

  • Aucune autorisation spécifique n'est requise pour générer une URL pré-signée. Toutefois, un tiers ne pourra charger un fichier avec succès via cette URL que si vous détenez l'autorisation oss:PutObject. Pour approfondir ce sujet, référez-vous au guide sur l'attribution d'une politique d'accès personnalisée à un utilisateur RAM.

  • L'exemple présenté repose sur une URL pré-signée V4, dont la durée de validité maximale est de 7 jours. Plus de détails sont disponibles dans la section consacrée à la Version de signature 4 (recommandée).

Processus

Pour charger un fichier en utilisant une URL signée et la méthode PUT, suivez la procédure ci-dessous :

image

Exemples de code

  1. Le propriétaire de l'objet génère une URL pré-signée destinée à une requête PUT.

    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 {
            // This example uses the public endpoint of the China (Hangzhou) region. Specify the 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 bucket name, for example, examplebucket.
            String bucketName = "examplebucket";
            // Specify the full path of the object, for example, exampleobject.txt. The full path of the object cannot contain the bucket name.
            String objectName = "exampleobject.txt";
            // Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou.
            String region = "cn-hangzhou";
    
            // Create an OSSClient instance.
            // When the OSSClient instance is no longer in use, call the shutdown method to release resources.
            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 expiration time of the generated presigned URL in milliseconds. This example sets the expiration time to 1 hour.
                Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
    
                // Generate a presigned URL.
                GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
                // Set the expiration time.
                request.setExpiration(expiration);
                // Generate a presigned URL for an HTTP PUT request.
                signedUrl = ossClient.generatePresignedUrl(request);
                // Print the presigned 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());
            }
        }
    }       
  2. Un autre utilisateur charge un fichier en exploitant l'URL pré-signée conçue pour la requête PUT.

    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 authorized URL.
            URL signedUrl = new URL("<signedUrl>");
    
            // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
            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 returned for the upload:"+response.getStatusLine().getStatusCode());
                if(response.getStatusLine().getStatusCode() == 200){
                    System.out.println("Upload successful using network library.");
                }
                System.out.println(response.toString());
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                 if (response != null) {
                     response.close();
                 }
                 if (httpClient != null) {
                     httpClient.close();
                 }
             }
        }
    }       

    Go

    package main
    
    import (
    	"fmt"
    	"io"
    	"net/http"
    	"os"
    )
    
    func uploadFile(signedUrl, filePath string) error {
    	// Open the file.
    	file, err := os.Open(filePath)
    	if err != nil {
    		return fmt.Errorf("Unable to open 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 request: %w", err)
    	}
    
    	// Send the request.
    	resp, err := client.Do(req)
    	if err != nil {
    		return fmt.Errorf("Failed to send 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 response: %w", err)
    	}
    
    	fmt.Printf("Status code returned for the upload: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Upload successful using network library.")
    	}
    	fmt.Println(string(body))
    
    	return nil
    }
    
    func main() {
    	// Replace <signedUrl> with the authorized URL.
    	signedUrl := "<signedUrl>"
    
    	// Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
    	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 file.
            with open(file_path, 'rb') as file:
                # Send a PUT request to upload the file.
                response = requests.put(signed_url, data=file)
         
            print(f"Status code returned for the upload: {response.status_code}")
            if response.status_code == 200:
                print("Upload successful using network library.")
            print(response.text)
     
        except Exception as e:
            print(f"An error occurred: {e}")
    
    if __name__ == "__main__":
        # Replace <signedUrl> with the authorized URL.
        signed_url = "<signedUrl>"
        
        # Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
        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 file.
            const response = await axios.put(signedUrl, fileStream, {
                headers: {
                    'Content-Type': 'application/octet-stream' // Adjust the Content-Type as needed.
                }
            });
    
            console.log(`Status code returned for the upload: ${response.status}`);
            if (response.status === 200) {
                console.log('Upload successful using network library.');
            }
            console.log(response.data);
        } catch (error) {
            console.error(`An error occurred: ${error.message}`);
        }
    }
    
    // Main function.
    (async () => {
        // Replace <signedUrl> with the authorized URL.
        const signedUrl = '<signedUrl>';
        
        // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
        const filePath = 'C:\\Users\\demo.txt';
    
        await uploadFile(signedUrl, filePath);
    })();

    browser.js

    Important

    Si vous rencontrez une erreur de discordance de signature 403 lors du chargement d'un fichier avec Browser.js, cela s'explique généralement par l'ajout automatique de l'en-tête de requête Content-Type par le navigateur, alors que cet en-tête n'avait pas été inclus lors de la génération de l'URL pré-signée. Cette incompatibilité entraîne un échec de la vérification de la signature. Pour résoudre ce problème, vous devez impérativement spécifier l'en-tête de requête Content-Type au moment de générer l'URL pré-signée.

    <!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 a file -->
        <input type="file" id="fileInput" />
        <button id="uploadButton">Upload File</button>
    
        <script>
            // Replace this with the presigned URL 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 the file to OSS.
             * @param {File} file - The file to upload.
             * @param {string} presignedUrl - The presigned URL.
             */
            const upload = async (file, presignedUrl) => {
                const response = await fetch(presignedUrl, {
                    method: 'PUT',
                    body: file,  // Upload the entire file directly.
                });
    
                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. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
    var filePath = "C:\\Users\\demo.txt";
    // Replace <signedUrl> with the authorized URL.
    var presignedUrl = "<signedUrl>";
    
    // Create an HTTP client and open the 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 the request.
    var response = await httpClient.SendAsync(request);
    
    // Process the response.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Upload successful! Status code: {response.StatusCode}");
        Console.WriteLine("Response headers:");
        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) {
            // Set the 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 file.
            FILE *file = fopen(filePath.c_str(), "rb");
            if (!file) {
                std::cerr << "Unable to open file: " << filePath << std::endl;
                return;
            }
    
            // Get the file size.
            fseek(file, 0, SEEK_END);
            long fileSize = ftell(file);
            fseek(file, 0, SEEK_SET);
    
            // Set the file size.
            curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
    
            // Set 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 returned for the upload: " << httpCode << std::endl;
    
                if (httpCode == 200) {
                    std::cout << "Upload successful using network library." << std::endl;
                }
            }
    
            // Close the file.
            fclose(file);
    
            // Clean up.
            curl_easy_cleanup(curl);
        }
    
        curl_global_cleanup();
    }
    
    int main() {
        // Replace <signedUrl> with the authorized URL.
        std::string signedUrl = "<signedUrl>";
    
        // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
        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 returned for the upload: " + responseCode);
    
                    if (responseCode == 200) {
                        Log.d(TAG, "Upload successful using network library.");
                    }
    
                    return "Upload complete. 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 authorized URL.
            String signedUrl = "<signedUrl>";
            // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
            String filePath = "C:\\Users\\demo.txt";
            activity.uploadFile(signedUrl, filePath);
        }
    }
    

Autres scénarios

Utiliser une URL signée pour téléverser un fichier avec des en-têtes de requête spécifiés et des métadonnées personnalisées

  1. Le propriétaire de l'objet génère une URL signée pour une requête PUT qui inclut les en-têtes de requête spécifiés ainsi que des métadonnées personnalisées.

    import com.aliyun.oss.*;
    import com.aliyun.oss.common.auth.*;
    import com.aliyun.oss.common.comm.SignVersion;
    import com.aliyun.oss.internal.OSSHeaders;
    import com.aliyun.oss.model.GeneratePresignedUrlRequest;
    import com.aliyun.oss.model.StorageClass;
    
    import java.net.URL;
    import java.util.*;
    import java.util.Date;
    
    public class GetSignUrl {
        public static void main(String[] args) throws Throwable {
            // This example uses the public endpoint of the China (Hangzhou) region. Specify the 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 bucket name, for example, examplebucket.
            String bucketName = "examplebucket";
            // Specify the full path of the object, for example, exampleobject.txt. The full path of the object cannot contain the bucket name.
            String objectName = "exampleobject.txt";
            // Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou.
            String region = "cn-hangzhou";
    
            // Create an OSSClient instance.
            // When the OSSClient instance is no longer in use, call the shutdown method to release resources.
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
            OSS ossClient = OSSClientBuilder.create()
                    .endpoint(endpoint)
                    .credentialsProvider(credentialsProvider)
                    .clientConfiguration(clientBuilderConfiguration)
                    .region(region)
                    .build();
    
            // Set the request headers.
            Map<String, String> headers = new HashMap<String, String>();
            // Specify the StorageClass.
            headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
            // Specify the ContentType.
            headers.put(OSSHeaders.CONTENT_TYPE, "text/plain; charset=utf8");
    
            // Set the custom user metadata.
            Map<String, String> userMetadata = new HashMap<String, String>();
            userMetadata.put("key1","value1");
            userMetadata.put("key2","value2");
    
            URL signedUrl = null;
            try {
                // Specify the expiration time of the generated presigned URL in milliseconds. This example sets the expiration time to 1 hour.
                Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
    
                // Generate a presigned URL.
                GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
                // Set the expiration time.
                request.setExpiration(expiration);
    
                // Add the request headers to the request.
                request.setHeaders(headers);
                // Add the custom user metadata.
                request.setUserMetadata(userMetadata);
    
                // Generate a presigned URL for an HTTP PUT request.
                signedUrl = ossClient.generatePresignedUrl(request);
                // Print the presigned 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());
            }
        }
    }       
  2. Un autre utilisateur téléverse un fichier en utilisant l'URL signée pour la requête PUT.

    curl

    curl -X PUT \
         -H "Content-Type: text/plain;charset=utf8" \
         -H "x-oss-storage-class: Standard" \
         -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=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"

    Java

    package com.aliyun.sample;
    
    import com.aliyun.oss.internal.OSSHeaders;
    import com.aliyun.oss.model.StorageClass;
    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 authorized URL.
            URL signedUrl = new URL("<signedUrl>");
    
            // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
            String pathName = "C:\\Users\\demo.txt";
    
            // Set the request headers. The request header information must be the same as the information used when the URL was 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 ContentType.
            headers.put(OSSHeaders.CONTENT_TYPE, "text/plain;charset=utf8");
    
            // Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was 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 you set header parameters, such as user metadata and storage class, when you generate the presigned URL, you must also send these parameters to the server when you use the presigned URL to upload the file. A signature error is reported if the parameters sent to the server are inconsistent with the signed parameters.
                for(Map.Entry<String, String> header: headers.entrySet()){
                    put.addHeader(header.getKey(), header.getValue());
                }
                for(Map.Entry<String, String> meta: userMetadata.entrySet()){
                    // If you use userMeta, the SDK internally adds the 'x-oss-meta-' prefix. When you use other methods to generate a presigned URL for an upload, you must also add the 'x-oss-meta-' prefix to the userMeta.
                    put.addHeader("x-oss-meta-"+meta.getKey(), meta.getValue());
                }
    
                httpClient = HttpClients.createDefault();
    
                response = httpClient.execute(put);
    
                System.out.println("Status code returned for the upload:"+response.getStatusLine().getStatusCode());
                if(response.getStatusLine().getStatusCode() == 200){
                    System.out.println("Upload successful using network library.");
                }
                System.out.println(response.toString());
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            }
        }
    }

    Go

    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 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
    	}
    
    	// Set the request headers.
    	for key, value := range headers {
    		req.Header.Set(key, value)
    	}
    
    	// Set the custom 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("Status code returned for the upload: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Upload successful using network library.")
    	} else {
    		fmt.Println("Upload failed.")
    	}
    	body, _ := ioutil.ReadAll(resp.Body)
    	fmt.Println(string(body))
    
    	return nil
    }
    
    func main() {
    	// Replace <signedUrl> with the authorized URL.
    	signedUrl := "<signedUrl>"
    
    	// Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
    	filePath := "C:\\Users\\demo.txt"
    
    	// Set the request headers. The request header information must be the same as the information used when the URL was generated.
    	headers := map[string]string{
    		"Content-Type": "text/plain;charset=utf8",
    		"x-oss-storage-class": "Standard",
    	}
    
    	// Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was 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)
    	}
    }
    

    Python

    import requests
    from requests.auth import HTTPBasicAuth
    import os
    
    def upload_file(signed_url, file_path, headers=None, metadata=None):
        """
        Use a presigned URL to upload a file to OSS.
    
        :param signed_url: The presigned URL.
        :param file_path: The full path of the file to upload.
        :param headers: Optional. Custom HTTP headers.
        :param metadata: Optional. Custom metadata.
        :return: None
        """
        if not headers:
            headers = {}
        if not metadata:
            metadata = {}
    
        # Update headers and add 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"Status code returned for the upload: {response.status_code}")
                if response.status_code == 200:
                    print("Upload successful using 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 authorized URL.
        signed_url = "<signedUrl>"
       
        # Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the directory where the script is located by default.
        file_path = "C:\\Users\\demo.txt"
    
        # Set the request headers. The request header information must be the same as the information used when the URL was generated.
        headers = {
             "Content-Type": "text/plain;charset=utf8",
             "x-oss-storage-class": "Standard"
        }
    
        # Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
        metadata = {
             "key1": "value1",
             "key2": "value2"
        }
    
        upload_file(signed_url, file_path, headers, metadata)
    

    Node.js

    const fs = require('fs');
    const axios = require('axios');
    
    async function uploadFile(signedUrl, filePath, headers = {}, metadata = {}) {
        try {
            // Update headers and add 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 a PUT request.
            const response = await axios.put(signedUrl, fileStream, {
                headers: headers
            });
    
            console.log(`Status code returned for the upload: ${response.status}`);
            if (response.status === 200) {
                console.log("Upload successful using network library.");
            } else {
                console.log("Upload failed.");
            }
            console.log(response.data);
        } catch (error) {
            console.error(`An error occurred: ${error.message}`);
        }
    }
    
    // Main function.
    (async () => {
        // Replace <signedUrl> with the authorized URL.
        const signedUrl = "<signedUrl>";
    
        // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the directory where the script is located by default.
        const filePath = "C:\\Users\\demo.txt";
    
        // Set the request headers. The request header information must be the same as the information used when the URL was generated.
        const headers = {
             "Content-Type": "text/plain;charset=utf8",
             "x-oss-storage-class": "Standard"
        };
    
        // Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
        const metadata = {
             "key1": "value1",
             "key2": "value2"
        };
    
        await uploadFile(signedUrl, filePath, headers, metadata);
    })();
    

    Browser.js

    Important

    Si vous rencontrez une erreur de non-correspondance de signature 403 lors de l'utilisation de Browser.js pour télécharger un fichier, cela est généralement dû au fait que le navigateur ajoute automatiquement l'en-tête de requête Content-Type, qui n'était pas inclus lors de la génération de l'URL pré-signée. Cette incompatibilité entraîne un échec de la vérification de la signature. Pour résoudre ce problème, vous devez spécifier l'en-tête de requête Content-Type lors de la génération de l'URL pré-signée.

    <!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 (Java SDK)</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 {
                    alert('Please select a file to upload.');
                }
            });
    
            const upload = async (file, presignedUrl) => {
                const headers = {
                    "Content-Type": "text/plain;charset=utf8",
                    'x-oss-storage-class': 'Standard',
                    'x-oss-meta-key1': 'value1',
                    'x-oss-meta-key2': 'value2'
                };
    
                const response = await fetch(presignedUrl, {
                    method: 'PUT',
                    headers: headers,
                    body: file
                });
    
                if (!response.ok) {
                    throw new Error(`Upload failed, status: ${response.status}`);
                }
    
                alert('File uploaded successfully');
                console.log('File uploaded successfully');
            };
        </script>
    </body>
    </html>

    C#

    using System.Net.Http.Headers;
    
    // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
    var filePath = "C:\\Users\\demo.txt";
    // Replace <signedUrl> with the authorized URL.
    var presignedUrl = "<signedUrl>";
    
    // Create an HTTP client and open the 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;
    
    // If you set header parameters, such as user metadata and storage class, when you generate the presigned URL, you must also send these parameters to the server when you use the presigned URL to upload the file. A signature error is reported if the parameters sent to the server are inconsistent with the signed parameters.
    // Set the request headers. The request header information must be the same as the information used when the URL was generated.
    request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain") { CharSet = "utf8" };  // Specify the ContentType.       
    // Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
    request.Content.Headers.Add("x-oss-meta-key1", "value1");
    request.Content.Headers.Add("x-oss-meta-key2", "value2");
    // Specify the storage class of the object.
    request.Content.Headers.Add("x-oss-storage-class", "Standard");
    
    // Print the request headers.
    Console.WriteLine("Request headers:");
    foreach (var header in request.Content.Headers)
    {
        Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
    }
    
    // Send the request.
    var response = await httpClient.SendAsync(request);
    
    // Process the response.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Upload successful! Status code: {response.StatusCode}");
        Console.WriteLine("Response headers:");
        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>
    #include <map>
    #include <string>
    
    // Callback function to handle 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) {
            // Set the 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 file.
            FILE* file = fopen(filePath.c_str(), "rb");
            if (!file) {
                std::cerr << "Unable to open file: " << filePath << std::endl;
                return;
            }
    
            // Set the file size.
            fseek(file, 0, SEEK_END);
            long fileSize = ftell(file);
            rewind(file);
    
            // Set the file read callback.
            curl_easy_setopt(curl, CURLOPT_READDATA, file);
            curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
    
            // Set the 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);
    
            // Set the response handling callback.
            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 << "Status code returned for the upload: " << responseCode << std::endl;
                if (responseCode == 200) {
                    std::cout << "Upload successful using 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 authorized URL.
        std::string signedUrl = "<signedUrl>";
    
        // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
        std::string filePath = "C:\\Users\\demo.txt";
    
        // Set the request headers. The request header information must be the same as the information used when the URL was generated.
        std::map<std::string, std::string> headers = {
             {"Content-Type", "text/plain;charset=utf8"},
             {"x-oss-storage-class", "Standard"}
        };
    
        // Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
        std::map<std::string, std::string> metadata = {
             {"key1", "value1"},
             {"key2", "value2"}
        };
    
        uploadFile(signedUrl, filePath, headers, metadata);
    
        return 0;
    }
    

    Android

    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 authorized URL.
            String signedUrl = "<signedUrl>";
    
            // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
            String pathName = "/storage/emulated/0/demo.txt";
    
            // Set the request headers. The request header information must be the same as the information used when the URL was generated.
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "text/plain;charset=utf8");
            headers.put("x-oss-storage-class", "Standard");
    
            // Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was 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);
    
                    // Set the request headers.
                    for (Entry<String, String> header : headers.entrySet()) {
                        connection.setRequestProperty(header.getKey(), header.getValue());
                    }
    
                    // Set the custom 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();
    
                    // Get the response.
                    int responseCode = connection.getResponseCode();
                    Log.d(TAG, "Status code returned for the upload: " + responseCode);
                    if (responseCode == 200) {
                        Log.d(TAG, "Upload successful using 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, "Upload successful.", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SignUrlUploadActivity.this, "Upload failed.", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
    

Utiliser une URL présignée pour effectuer un chargement en plusieurs parties

Pour réaliser un chargement multipart via une URL présignée, vous devez configurer la taille des parties et générer une URL présignée pour chacune d’elles. L’extrait de code ci-dessous illustre cette démarche :

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.internal.Mimetypes;
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 {
        // This example uses the public endpoint of the China (Hangzhou) region. Specify the 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 bucket name, for example, examplebucket.
        String bucketName = "examplebucket";
        // Specify the full path of the object, for example, exampleobject.txt. The full path of the object cannot contain the bucket name.
        String objectName = "exampleobject.txt";
        // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
        String pathName = "D:\\localpath\\examplefile.txt";
        // Specify the expiration time of the generated presigned URL in milliseconds. This example sets the expiration time to 1 hour.
        long expireTime = 3600*1000L;
        // Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou.
        String region = "cn-hangzhou";

        // Create an OSSClient instance.
        // When the OSSClient instance is no longer in use, call the shutdown method to release resources.
        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);
        ObjectMetadata metadata = new ObjectMetadata();
        // Automatically set the ContentType based on the file. If this parameter is not set, the ContentType defaults to application/octet-stream.
        if (metadata.getContentType() == null) {
            metadata.setContentType(Mimetypes.getInstance().getMimetype(new File(pathName), objectName));
        }

        initRequest.setObjectMetadata(metadata);
        // Initialize the multipart upload.
        InitiateMultipartUploadResult upResult = ossClient.initiateMultipartUpload(initRequest);
        // The uploadId is returned. The uploadId is the unique identifier for the multipart upload event. You can use this uploadId to perform related operations, such as canceling or querying the multipart upload.
        String uploadId = upResult.getUploadId();

        // partETags is a collection of PartETags. A PartETag consists of the ETag and part number of a part.
        List<PartETag> partETags =  new ArrayList<PartETag>();
        // The size of each part in bytes, which is used to calculate the number of parts for the file.
        long partSize = 1 * 100 * 1024L;   // 100 KB.

        // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
        File sampleFile = new File(pathName);
        long fileLength = sampleFile.length();
        // If you want to have only one part, set the part size to the file size.
        // long fileLength = sampleFile.length();
        int partCount = (int) (fileLength / partSize);
        if (fileLength % partSize != 0) {
            partCount++;
        }

        // Set the request headers for the presigned URL.
        Map<String, String> headers = new HashMap<String, String>();
        // Specify the ContentType.
        // headers.put(OSSHeaders.CONTENT_TYPE, "text/plain");

        // Traverse the parts to obtain the signature for each part and upload the parts.
        // You can also return the presigned URLs for all parts at once and then upload them sequentially. This example shows how to return a single presigned URL and upload a single part using the presigned URL.
        for (int i = 0; i < partCount; i++) {
            long startPos = i * partSize;
            long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;

            /*// Set MD5 verification. MD5 verification is supported only for a single part.
            FileInputStream inStream = new FileInputStream(pathName);
            // Skip the uploaded parts.
            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);

            // Upload the file using the presigned URL. This example uses HttpClients.
            putObjectWithHttp(signUrl, pathName, startPos, curPartSize, headers);
        }

        // Assume that when you merge the parts, you are on a different system from the one used to upload the parts. In this case, you must first list the parts and then merge them.
        // 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);
        }

        // Merge the parts.
        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
        // String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5("aaa".getBytes()));
        // Forbid overwriting an object that has the same name.
        // completeMultipartUploadRequest.addHeader("x-oss-forbid-overwrite", "true");

        // Complete the multipart upload.
        CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
        System.out.println("The parts are merged and the multipart upload is complete.");

        // Verify the integrity of the uploaded file.
        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 uploaded parts.
            inStream.skip(startPos);
            InputStreamEntity entity = new InputStreamEntity(inStream, partSize);
            BufferedHttpEntity byteArrayEntity = new BufferedHttpEntity(entity);
            put.setEntity(byteArrayEntity);

            // If you set header parameters, such as user metadata and storage class, when you generate the presigned URL, you must also send these parameters to the server when you use the presigned URL to upload the file. A signature error is reported if the parameters sent to the server are inconsistent with the signed parameters.
            for(Map.Entry header: headers.entrySet()){
                put.addHeader(header.getKey().toString(),header.getValue().toString());
            }

            // Add a retry mechanism. The number of retries is set to 3. This is just an example. Set the number of retries as needed for your business.
            httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)).build();

            response = httpClient.execute(put);

            System.out.println("Status code returned for the upload:"+response.getStatusLine().getStatusCode());
            if(response.getStatusLine().getStatusCode() == 200){
                System.out.println("Upload successful using network 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 expiration time of the generated presigned URL in milliseconds.
        Date expiration = new Date(new Date().getTime() + expireTime);

        // Generate a presigned URL.
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, method);
        // Set the expiration time.
        request.setExpiration(expiration);

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

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

        request.addQueryParameter("uploadId", uploadId);

        // Generate a presigned URL for an HTTP method request.
        URL signedUrl = ossClient.generatePresignedUrl(request);
        // Print the presigned URL.
        System.out.println("signed url: " + signedUrl);
        return signedUrl.toString();
    }
}

Utiliser une URL présignée pour charger un fichier et définir les paramètres de rappel de chargement

  1. Le propriétaire de l’objet génère une URL présignée pour une requête PUT incluant des paramètres de rappel de chargement spécifiques.

    import com.aliyun.oss.*;
    import com.aliyun.oss.common.auth.CredentialsProviderFactory;
    import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
    import com.aliyun.oss.common.comm.SignVersion;
    import com.aliyun.oss.internal.OSSHeaders;
    import com.aliyun.oss.model.GeneratePresignedUrlRequest;
    
    import java.net.URL;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    public class OssPresignExample {
        public static void main(String[] args) throws Throwable {
            // This example uses the public endpoint of the China (Hangzhou) region. Specify the 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 bucket name, for example, examplebucket.
            String bucketName = "examplebucket";
            // Specify the full path of the object, for example, exampleobject.txt. The full path of the object cannot contain the bucket name.
            String objectName = "exampleobject.txt";
            // Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou.
            String region = "cn-hangzhou";
    
            // Create an OSSClient instance.
            // When the OSSClient instance is no longer in use, call the shutdown method to release resources.
            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 {
                // Construct the callback parameters.
                String callbackUrl = "http://www.example.com/callback";
                String callbackBody = "{\"callbackUrl\":\"" + callbackUrl + "\",\"callbackBody\":\"bucket=${bucket}&object=${object}&my_var_1=${x:var1}&my_var_2=${x:var2}\"}";
                String callbackBase64 = Base64.getEncoder().encodeToString(callbackBody.getBytes());
    
                String callbackVarJson = "{\"x:var1\":\"value1\",\"x:var2\":\"value2\"}";
                String callbackVarBase64 = Base64.getEncoder().encodeToString(callbackVarJson.getBytes());
                // Set the request headers.
                Map<String, String> headers = new HashMap<String, String>();
                // Specify CALLBACK.
                headers.put(OSSHeaders.OSS_HEADER_CALLBACK, callbackBase64);
                // Specify CALLBACK-VAR.
                headers.put(OSSHeaders.OSS_HEADER_CALLBACK_VAR, callbackVarBase64);
    
                // Set the expiration time (3600 seconds later).
                Date expiration = new Date(new Date().getTime() + 3600 * 1000);
    
                // Format the expiration time.
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                String expirationStr = dateFormat.format(expiration);
    
                // Construct the request.
                GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName);
                request.setMethod(HttpMethod.PUT);
                request.setExpiration(expiration);
                // Add the request headers to the request.
                request.setHeaders(headers);
    
                // Print the callback and callback-var parameters.
                System.out.println("callback:"+callbackBase64);
                System.out.println("callback-var:"+callbackVarBase64);
    
                // Generate the presigned URL.
                URL url = ossClient.generatePresignedUrl(request);
    
                // Print the result.
                System.out.println("method: PUT,");
                System.out.println(" expiration: " + expirationStr + ",");
                System.out.println(" url: " + url);
    
            } 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());
            }
        }
    }
  2. Un autre utilisateur charge un fichier en utilisant l’URL présignée associée à la requête PUT.

    curl

    curl -X PUT \
         -H "x-oss-callback: eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9" \
         -H "x-oss-callback-var: eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==" \
         -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=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"

    Python

    import requests
    
    def upload_file(signed_url, file_path, headers=None):
        """
        Upload a file to OSS using a presigned URL.
    
        :param signed_url: The presigned URL.
        :param file_path: The full path of the file to upload.
        :param headers: Optional. Custom HTTP headers.
        :return: None
        """
        if not headers:
            headers = {}
    
        try:
            with open(file_path, 'rb') as file:
                response = requests.put(signed_url, data=file, headers=headers)
                print(f"Upload status code returned: {response.status_code}")
                if response.status_code == 200:
                    print("Upload successful 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 authorized URL.
        signed_url = "<signedUrl>"
    
        # Enter the full path of the local file. If you do not specify a local path, the file is uploaded from the directory where the script is located by default.
        file_path = "C:\\Users\\demo.txt"
    
        headers = {
            "x-oss-callback": "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9",
            "x-oss-callback-var": "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==",
        }
    
        upload_file(signed_url,  file_path, headers)

    Go

    package main
    
    import (
        "bytes"
        "fmt"
        "io"
        "net/http"
        "os"
    )
    
    func uploadFile(signedUrl string, filePath string, headers map[string]string) error {
        // Open the file.
        file, err := os.Open(filePath)
        if err != nil {
            return err
        }
        defer file.Close()
    
        // Read the file content.
        fileBytes, err := io.ReadAll(file)
        if err != nil {
            return err
        }
    
        // Create a request.
        req, err := http.NewRequest("PUT", signedUrl, bytes.NewBuffer(fileBytes))
        if err != nil {
            return err
        }
    
        // Set request headers.
        for key, value := range headers {
            req.Header.Add(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 returned: %d\n", resp.StatusCode)
        if resp.StatusCode == 200 {
            fmt.Println("Upload successful using the network library.")
        } else {
            fmt.Println("Upload failed.")
        }
        body, _ := io.ReadAll(resp.Body)
        fmt.Println(string(body))
    
        return nil
    }
    
    func main() {
        // Replace <signedUrl> with the authorized URL.
        signedUrl := "<signedUrl>"
        // Enter the full path of the local file. If you do not specify a local path, the file is uploaded from the project's corresponding local path by default.
        filePath := "C:\\Users\\demo.txt"
    
        // Set request headers. The header information here must be consistent with the information used to generate the URL.
        headers := map[string]string{
            "x-oss-callback":     "eyJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9XHUwMDI2b2JqZWN0PSR7b2JqZWN0fVx1MDAyNnNpemU9JHtzaXplfVx1MDAyNm15X3Zhcl8xPSR7eDpteV92YXIxfVx1MDAyNm15X3Zhcl8yPSR7eDpteV92YXIyfSIsImNhbGxiYWNrQm9keVR5cGUiOiJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiLCJjYWxsYmFja1VybCI6Imh0dHA6Ly9leGFtcGxlLmNvbToyMzQ1MCJ9",
            "x-oss-callback-var": "eyJ4Om15X3ZhcjEiOiJ0aGkgaXMgdmFyIDEiLCJ4Om15X3ZhcjIiOiJ0aGkgaXMgdmFyIDIifQ==",
        }
    
        err := uploadFile(signedUrl, filePath, headers)
        if err != nil {
            fmt.Printf("An error occurred: %v\n", err)
        }
    }

    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 IOException {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
    
        // Replace <signedUrl> with the authorized URL.
        URL signedUrl = new URL("<signedUrl>");
    
        // Enter the full path of the local file. If you do not specify a local path, the file is uploaded from the project's corresponding local path by default.
        String pathName = "C:\\Users\\demo.txt";
    
        // Set request headers, including x-oss-callback and x-oss-callback-var.
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("x-oss-callback", "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9");
        headers.put("x-oss-callback-var", "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==");
    
        try {
          HttpPut put = new HttpPut(signedUrl.toString());
          System.out.println(put);
          HttpEntity entity = new FileEntity(new File(pathName));
          put.setEntity(entity);
          // If header parameters were set when generating the presigned URL, these parameters must also be sent to the server when using the presigned URL to upload the file. If the signature and the parameters sent to the server do not match, a signature error will occur.
          for(Map.Entry<String, String> header: headers.entrySet()){
            put.addHeader(header.getKey(),header.getValue());
          }
    
          httpClient = HttpClients.createDefault();
    
          response = httpClient.execute(put);
    
          System.out.println("Upload status code returned:"+response.getStatusLine().getStatusCode());
          if(response.getStatusLine().getStatusCode() == 200){
            System.out.println("Upload successful using the network library.");
          }
          System.out.println(response.toString());
        } catch (Exception e){
          e.printStackTrace();
        } finally {
          if (response != null) {
            response.close();
          }
          if (httpClient != null) {
            httpClient.close();
          }
        }
      }
    }       

    PHP

    <?php
    
    function uploadFile($signedUrl, $filePath, $headers = []) {
        // Check if the file exists.
        if (!file_exists($filePath)) {
            echo "File does not exist: $filePath\n";
            return;
        }
    
        // Initialize cURL session.
        $ch = curl_init();
    
        // Set cURL options.
        curl_setopt($ch, CURLOPT_URL, $signedUrl);
        curl_setopt($ch, CURLOPT_PUT, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_INFILE, fopen($filePath, 'rb'));
        curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filePath));
        curl_setopt($ch, CURLOPT_HTTPHEADER, array_map(function($key, $value) {
            return "$key: $value";
        }, array_keys($headers), $headers));
    
        // Execute cURL request.
        $response = curl_exec($ch);
    
        // Get HTTP status code.
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
        // Close cURL session.
        curl_close($ch);
    
        // Output the result.
        echo "Upload status code returned: $httpCode\n";
        if ($httpCode == 200) {
            echo "Upload successful using the network library.\n";
        } else {
            echo "Upload failed.\n";
        }
        echo $response . "\n";
    }
    
    // Replace <signedUrl> with the authorized URL.
    $signedUrl = "<signedUrl>";
    
    // Enter the full path of the local file. If you do not specify a local path, the file is uploaded from the directory where the script is located by default.
    $filePath = "C:\\Users\\demo.txt";
    
    $headers = [
        "x-oss-callback" => "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9",
        "x-oss-callback-var" => "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==",
    ];
    
    uploadFile($signedUrl, $filePath, $headers);
    
    ?>

FAQ

Si une signature temporaire expire pendant le téléversement d’un fichier, l’opération échoue-t-elle ?

Le téléversement aboutit.

La requête de téléversement doit être initiée tant que l’URL pré-signée est valide. La durée de validité de l’URL correspond à la valeur la plus courte entre la durée de validité du jeton et celle de l’URL pré-signée.

Si je ne définis pas les en-têtes de requête ni les métadonnées personnalisées lors de la génération de l’URL, dois-je les configurer lors du téléversement via cette URL ?

Aucune configuration n’est requise.

Les en-têtes de requête et les métadonnées personnalisées sont des paramètres facultatifs. Si vous ne renseignez pas ces paramètres, vous pouvez supprimer le code associé des exemples.

Références

  • Pour obtenir l’exemple de code complet permettant de générer une URL pré-signée V4, consultez l’exemple GitHub.

  • Pour en savoir plus sur l’opération API permettant de téléverser un fichier à l’aide d’une URL pré-signée, consultez GeneratePresignedUrlRequest.