Todos os produtos
Search
Central de documentação

Object Storage Service:Faça upload de objetos com uma URL pré-assinada usando o OSS SDK for PHP 2.0

Última atualização: Sep 24, 2026

Por padrão, a lista de controle de acesso (ACL) de um objeto em um bucket do Object Storage Service (OSS) é privada, ou seja, apenas o proprietário do objeto tem permissão para acessá-lo. Este tópico descreve como usar o OSS SDK for PHP para gerar uma URL pré-assinada que permite ao usuário fazer o upload de um objeto específico em um período determinado por meio do método HTTP PUT. Durante o período de validade, o usuário pode acessar o objeto repetidamente pela URL pré-assinada. Se a URL pré-assinada expirar, gere uma nova URL pré-assinada para estender o acesso do usuário.

Observações

  • O código de exemplo neste tópico usa o ID de região cn-hangzhou da região China (Hangzhou). Por padrão, utiliza-se um endpoint público para acessar recursos em um bucket. Para acessar recursos no bucket a partir de outros serviços da Alibaba Cloud na mesma região do bucket, use um endpoint interno. Para mais informações sobre as regiões e os endpoints compatíveis, consulte Regions and endpoints.

  • Gerar uma URL pré-assinada não exige permissões. No entanto, um terceiro só consegue fazer o upload de um arquivo com a URL pré-assinada se você possuir a permissão oss:PutObject. Para mais informações, consulte Grant a custom access policy to a RAM user.

  • Neste tópico, utiliza-se o algoritmo de assinatura V4 para gerar URLs pré-assinadas com validade de até 7 dias. Para mais informações, consulte (Recommended) V4 signatures in presigned URLs.

  • Neste tópico, o código obtém as credenciais de acesso de variáveis de ambiente. Para mais informações, consulte Configure access credentials for OSS SDK for PHP.

Processo

Para fazer o upload de um arquivo usando uma URL assinada e o método PUT, siga este procedimento:

image

Código de exemplo

  1. O proprietário do objeto gera uma URL pré-assinada que permite solicitações HTTP PUT.

    Importante

    Ao especificar cabeçalhos de solicitação na geração de uma URL pré-assinada que permite solicitações HTTP PUT, inclua esses cabeçalhos na solicitação PUT iniciada pela URL pré-assinada. Essa prática evita falhas de solicitação e erros de assinatura.

    <?php
    
    // Include the autoload file to load dependencies.
    require_once __DIR__ . '/../vendor/autoload.php';
    
    use AlibabaCloud\Oss\V2 as Oss;
    
    // Define and describe command-line options.
    $optsdesc = [
        "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // (Required) Specify the region in which the bucket is located.
        "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // (Optional) Specify the endpoint for accessing OSS.
        "bucket" => ['help' => 'The name of the bucket', 'required' => True], // (Required) Specify the name of the bucket.
        "key" => ['help' => 'The name of the object', 'required' => True], // (Required) Specify the name of the object.
    ];
    
    // Convert the descriptions to a list of long options required by getopt.
    // Add a colon (:) to the end of each option to indicate that a value is required.
    $longopts = \array_map(function ($key) {
        return "$key:";
    }, array_keys($optsdesc));
    
    // Parse the command-line options.
    $options = getopt("", $longopts);
    
    // Check whether required options are missing.
    foreach ($optsdesc as $key => $value) {
        if ($value['required'] === True && empty($options[$key])) {
            $help = $value['help']; // Obtain help information.
            echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
            exit(1); // Exit the program if a required option is missing.
        }
    }
    
    // Assign the values parsed from the command-line options to the corresponding variables.
    $region = $options["region"]; // The region in which the bucket is located.
    $bucket = $options["bucket"]; // The name of the bucket.
    $key = $options["key"]; // The name of the object 
    
    // Load access credentials from environment variables.
    // Use EnvironmentVariableCredentialsProvider to retrieve the AccessKey ID and AccessKey secret from environment variables.
    $credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
    
    // Use the default configuration of the SDK.
    $cfg = Oss\Config::loadDefault();
    $cfg->setCredentialsProvider($credentialsProvider); // Specify the credential provider.
    $cfg->setRegion($region); // Specify the region in which the bucket is located.
    if (isset($options["endpoint"])) {
        $cfg->setEndpoint($options["endpoint"]); // Specify the endpoint if one is provided.
    }
    
    // Create an OSS client instance.
    $client = new Oss\Client($cfg);
    
    // Create a PutObjectRequest object to upload the data.
    $request = new Oss\Models\PutObjectRequest(bucket: $bucket, key: $key);
    
    // Call the presign method to generate a presigned request.
    $result = $client->presign($request);
    
    // Display the result of the presign operation.
    // Display the presigned URL, which can be used to upload the specified object.
    print(
        'put object presign result:' . var_export($result, true) . PHP_EOL . // The details of the presign result.
        'put object url:' . $result->url . PHP_EOL                           // The presigned URL.
    );
    
  2. O usuário utiliza a URL pré-assinada para fazer o upload de um objeto.

    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

    Importante

    Ao encontrar um erro de incompatibilidade de assinatura 403 ao usar o Node.js para fazer o upload de um arquivo, geralmente o motivo é a definição explícita do cabeçalho de solicitação Content-Type na solicitação de upload sem a inclusão desse cabeçalho na geração da URL pré-assinada. Essa incompatibilidade causa falha na verificação de assinatura. Para resolver esse problema, não defina o cabeçalho de solicitação Content-Type na solicitação de upload ou especifique o cabeçalho de solicitação Content-Type ao gerar a URL pré-assinada.

    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);
    
            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

    Importante

    Ao encontrar um erro de incompatibilidade de assinatura 403 ao usar o Browser.js para fazer o upload de um arquivo, geralmente o motivo é a adição automática do cabeçalho de solicitação Content-Type pelo navegador sem a inclusão desse cabeçalho na geração da URL pré-assinada. Essa incompatibilidade causa falha na verificação de assinatura. Para resolver esse problema, especifique o cabeçalho de solicitação Content-Type ao gerar a URL pré-assinada.

    <!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);
        }
    }
    

Cenários comuns

Use uma URL pré-assinada que contenha cabeçalhos de solicitação e metadados do usuário específicos para fazer o upload de um arquivo

  1. O proprietário do objeto gera uma URL pré-assinada que permite solicitações HTTP PUT.

    <?php
    
    // Include the autoload file to load dependencies.
    require_once __DIR__ . '/../vendor/autoload.php';
    
    use AlibabaCloud\Oss\V2 as Oss;
    
    // Define and describe command-line options.
    $optsdesc = [
        "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // (Required) Specify the region in which the bucket is located.
        "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // (Optional) Specify the endpoint for accessing OSS.
        "bucket" => ['help' => 'The name of the bucket', 'required' => True], // (Required) Specify the name of the bucket.
        "key" => ['help' => 'The name of the object', 'required' => True], // (Required) Specify the name of the object.
    ];
    
    // Convert the descriptions to a list of long options required by getopt.
    // Add a colon (:) to the end of each option to indicate that a value is required.
    $longopts = \array_map(function ($key) {
        return "$key:";
    }, array_keys($optsdesc));
    
    // Parse the command-line options.
    $options = getopt("", $longopts);
    
    // Check whether required options are missing.
    foreach ($optsdesc as $key => $value) {
        if ($value['required'] === True && empty($options[$key])) {
            $help = $value['help']; // Obtain help information.
            echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
            exit(1); // Exit the program if a required option is missing.
        }
    }
    
    // Assign the values parsed from the command-line options to the corresponding variables.
    $region = $options["region"]; // The region in which the bucket is located.
    $bucket = $options["bucket"]; // The name of the bucket.
    $key = $options["key"];       // The name of the object.
    
    // Load access credentials from environment variables.
    // Use EnvironmentVariableCredentialsProvider to retrieve the AccessKey ID and AccessKey secret from environment variables.
    $credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
    
    // Use the default configuration of the SDK.
    $cfg = Oss\Config::loadDefault();
    $cfg->setCredentialsProvider($credentialsProvider); // Specify the credential provider.
    $cfg->setRegion($region); // Specify the region in which the bucket is located.
    if (isset($options["endpoint"])) {
        $cfg->setEndpoint($options["endpoint"]); // Specify the endpoint if one is provided.
    }
    
    // Create an OSS client instance.
    $client = new Oss\Client($cfg);
    
    // Set the content type to text.
    $contentType = "text/plain; charset=utf-8";
    
    // Specify custom metadata.
    $metadata = [
        "key1" => "value1",
        "key2" => "value2",
    ];
    
    // Create a PutObjectRequest object to upload the data. Note that the contentType and metadata parameters are included for signature calculation. 
    $request = new Oss\Models\PutObjectRequest(bucket: $bucket, key: $key, contentType: $contentType, metadata: $metadata);
    
    // Call the presign method to generate a presigned request.
    $result = $client->presign($request);
    
    // Display the result of the presign operation.
    // Display the presigned URL, which can be used to upload the specified object.
    print(
        'put object presign result:' . var_export($result, true) . PHP_EOL . // The details of the presign result.
        'put object url:' . $result->url . PHP_EOL                           // The presigned URL.
    );
    
  2. O usuário utiliza a URL pré-assinada para fazer o upload de um objeto.

    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

    Importante

    Ao encontrar um erro de incompatibilidade de assinatura 403 ao usar o Browser.js para fazer o upload de um arquivo, geralmente o motivo é a adição automática do cabeçalho de solicitação Content-Type pelo navegador sem a inclusão desse cabeçalho na geração da URL pré-assinada. Essa incompatibilidade causa falha na verificação de assinatura. Para resolver esse problema, especifique o cabeçalho de solicitação Content-Type ao gerar a URL pré-assinada.

    <!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();
                }
            }
        }
    }
    

Use URLs pré-assinadas para o upload de múltiplas partes

O código de exemplo a seguir demonstra a geração de uma URL pré-assinada para cada parte e como usá-las para fazer o upload de um objeto em partes:

<?php

// Include the autoload file to load dependencies.
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;
use GuzzleHttp\Psr7\LazyOpenStream;
use GuzzleHttp\Client;

// Define and describe command-line options.
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => true],
    "bucket" => ['help' => 'The name of the bucket', 'required' => true],
    "key" => ['help' => 'The name of the object', 'required' => true],
];

// Create a list of long options required by getopt.
$longopts = array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

// Parse the command-line options.
$options = getopt("", $longopts);

// Check whether required options are missing.
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === true && empty($options[$key])) {
        echo "Error: the following arguments are required: --$key, " . $value['help'] . "\n";
        exit(1);
    }
}

// Assign the values parsed from the command-line options to the corresponding variables.
$region = $options["region"];
$bucket = $options["bucket"];
$key = $options["key"];

// Specify the local file path.
$bigFileName = "/Users/localpath/yourfilename"; // Replace the value with the path of the actual file to upload.
$partSize = 1 * 1024 * 1024; // Set the part size. In this example, the part size is 1 MB.
$fileSize = filesize($bigFileName); // Query the total size of the file.
$partsNum = intdiv($fileSize, $partSize) + (int)($fileSize % $partSize > 0 ? 1 : 0); // Calculate the number of parts.

// Load access credentials from environment variables.
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// Use the default configuration, and specify the credential provider and region.
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider);
$cfg->setRegion($region);

// Create a client instance.
$client = new Oss\Client($cfg);

// Step 1: Iniate the multipart upload.
// Call the InitiateMultipartUpload method and get the upload ID.
$initResult = $client->initiateMultipartUpload(
    new Oss\Models\InitiateMultipartUploadRequest(
        bucket: $bucket,
        key: $key
    )
);

// Save the upload ID returned.
$uploadId = $initResult->uploadId;

// Step 2: Loop through each part to create a presigned URL for each part and upload the part.
$parts = []; // Store the ETag and number of each part.

for ($i = 1; $i <= $partsNum; $i++) {
    // Create a UploadPartRequest object.
    $request = new Oss\Models\UploadPartRequest(
        bucket: $bucket,
        key: $key,
        partNumber: $i,
        uploadId: $uploadId
    );

    // Generate a presigned URL for a part to allow part upload using an external client.
    $signedResult = $client->presign($request);

    // Get the presigned URL and request method.
    $signedUrl = $signedResult->url;
    $method = $signedResult->method;

    // Calculate the offset of the current part and its length.
    $offset = ($i - 1) * $partSize;
    $length = min($partSize, $fileSize - $offset);

    // Open a large file stream, seek to the offset of the current part, and read the content.
    $file = new LazyOpenStream($bigFileName, 'rb');
    $file->seek($offset);
    $content = $file->read($length);

    // Use the HTTP client to send a PUT request for uploading the part.
    $http = new Client();
    $response = $http->request($method, $signedUrl, [
        'body' => $content
    ]);

    // Get the ETag from the response, which will be used for combining parts into an object.
    $etag = $response->getHeaderLine('ETag');

    // Store part information in the array, which will be used to send a CompleteMultipartUpload request.
    $parts[] = new Oss\Models\UploadPart(
        partNumber: $i,
        etag: $etag
    );

    // (Optional) Display the upload progress.
    echo "Upload part {$i} success. ETag: {$etag}\n";
}

// Step 3: Complete the multipart upload.
// Create a CompleteMultipartUploadRequest to combine all parts.
$completeRequest = new Oss\Models\CompleteMultipartUploadRequest(
    bucket: $bucket,
    key: $key,
    uploadId: $uploadId,
    completeMultipartUpload: new Oss\Models\CompleteMultipartUpload(
        parts: $parts
    )
);

// Send the request.
$comResult = $client->completeMultipartUpload($completeRequest);

// Display response details.
printf(
    'status code: %s' . PHP_EOL .
    'request id: %s' . PHP_EOL .
    'complete multipart upload result: %s' . PHP_EOL,
    $comResult->statusCode,
    $comResult->requestId,
    var_export($comResult, true)
);

Use uma URL pré-assinada para fazer o upload de um objeto e definir parâmetros de callback do upload

  1. O proprietário do objeto gera uma URL pré-assinada que inclui parâmetros de callback do upload e permite solicitações HTTP PUT.

    <?php
    
    // Include the autoload file to load dependencies.
    require_once __DIR__ . '/../vendor/autoload.php';
    
    use AlibabaCloud\Oss\V2 as Oss;
    
    // Define and describe command-line options.
    $optsdesc = [
        "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // (Required) Specify the region in which the bucket is located.
        "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // (Optional) Specify the endpoint for accessing OSS.
        "bucket" => ['help' => 'The name of the bucket', 'required' => True], // (Required) Specify the name of the bucket.
        "key" => ['help' => 'The name of the object', 'required' => True], // (Required) Specify the name of the object.
    ];
    
    // Convert the descriptions to a list of long options required by getopt.
    // Add a colon (:) to the end of each option to indicate that a value is required.
    $longopts = \array_map(function ($key) {
        return "$key:";
    }, array_keys($optsdesc));
    
    // Parse the command-line options.
    $options = getopt("", $longopts);
    
    // Check whether the required options are configured.
    foreach ($optsdesc as $key => $value) {
        if ($value['required'] === True && empty($options[$key])) {
            $help = $value['help']; // Obtain help information.
            echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
            exit(1); // Exit the program if a required option is missing.
        }
    }
    
    // Assign the values parsed from the command-line options to the corresponding variables.
    $region = $options["region"]; // The region in which the bucket is located.
    $bucket = $options["bucket"]; // The name of the bucket.
    $key = $options["key"];       // The name of the object.
    
    // Load access credentials from environment variables.
    // Use EnvironmentVariableCredentialsProvider to retrieve the AccessKey ID and AccessKey secret from environment variables.
    $credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
    
    // Use the default configuration of the SDK.
    $cfg = Oss\Config::loadDefault();
    $cfg->setCredentialsProvider($credentialsProvider); // Specify the credential provider.
    $cfg->setRegion($region); // Specify the region in which the bucket is located.
    if (isset($options["endpoint"])) {
        $cfg->setEndpoint($options["endpoint"]); // Specify the endpoint if one is provided.
    }
    
    // Create an OSSClient instance.
    $client = new Oss\Client($cfg);
    
    // Include the x-oss-callback and x-oss-callback-var headers.
    // Specify the callback URL.
    $call_back_url = "http://www.example.com/callback";
    
    // Construct callback parameters: Specify the callback URL and request body, both of which must be Base64-encoded.
    // Replace ${x:var1} and ${x:var2} with placeholders {var1} and {var2}.
    $callback_body_template = "bucket={bucket}&object={object}&my_var_1={var1}&my_var_2={var2}";
    $callback_body_replaced = str_replace(
        ['{bucket}', '{object}', '{var1}', '{var2}'],
        [$bucket, $key, 'value1', 'value2'],
        $callback_body_template
    );
    $callback = base64_encode(json_encode([
        "callbackUrl" => $call_back_url,
        "callbackBody" => $callback_body_replaced
    ]));
    
    // Define and Base64-encode custom callback variables.
    $callback_var = base64_encode(json_encode([
        "x:var1" => "value1",
        "x:var2" => "value2"
    ]));
    
    // Create a PutObjectRequest object to upload the data. 
    // Note that the Content-Type, metadata, and headers are included for signature calculation. 
    $request = new Oss\Models\PutObjectRequest(
        bucket: $bucket,
        key: $key,
        callback:$callback,
        callbackVar:$callback_var,
    );
    
    // Call the presign method to generate a presigned request.
    $result = $client->presign($request);
    
    // Display the presigned URL, which can be used to upload the specified object.
    print(
        'put object presign result:' . var_export($result, true) . PHP_EOL .
        'put object url:' . $result->url . PHP_EOL
    );
    
  2. Outro usuário faz o upload de um arquivo usando a URL pré-assinada para o método 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);
    
    ?>

Referências

  • Para acessar o código de exemplo completo sobre o uso de URLs pré-assinadas, visite o GitHub.

  • Para mais informações sobre a operação da API que gera uma URL pré-assinada, consulte Presign.