All Products
Search
Document Center

Object Storage Service:Mengunggah objek menggunakan URL yang ditandatangani (C# SDK V2)

Last Updated:Nov 09, 2025

Secara default, objek di Bucket OSS bersifat privat. Hanya pemilik objek yang memiliki izin untuk mengunggah objek. Anda dapat menggunakan OSS C# SDK untuk menghasilkan URL yang telah ditandatangani, memungkinkan pengguna lain untuk mengunggah objek. Saat menghasilkan URL yang telah ditandatangani, Anda dapat menentukan waktu kedaluwarsa untuk membatasi durasi akses. URL tersebut dapat digunakan beberapa kali sebelum kedaluwarsa. Jika beberapa operasi unggah dilakukan, objek mungkin akan ditimpa. Setelah URL kedaluwarsa, Anda tidak dapat menggunakannya lagi untuk unggahan dan harus menghasilkan URL baru yang telah ditandatangani.

Precautions

  • Kode contoh dalam topik ini menggunakan Wilayah China (Hangzhou), dengan ID wilayah cn-hangzhou, sebagai contoh. Titik akhir publik digunakan secara default. Jika Anda ingin mengakses OSS dari layanan Alibaba Cloud lainnya di wilayah yang sama dengan OSS, gunakan titik akhir internal. Untuk informasi lebih lanjut tentang wilayah dan titik akhir yang didukung oleh OSS, lihat Wilayah dan Titik Akhir OSS.

  • Anda tidak memerlukan izin khusus untuk menghasilkan URL yang ditandatangani. Namun, untuk mengizinkan orang lain menggunakan URL yang ditandatangani untuk mengunggah objek, Anda harus memiliki izin oss:PutObject. Untuk informasi lebih lanjut, lihat Mengotorisasi Pengguna RAM untuk Mengakses Beberapa Direktori dalam Bucket.

Proses

Gambar berikut menunjukkan cara menggunakan URL yang ditandatangani untuk mengizinkan permintaan HTTP PUT mengunggah objek ke OSS.

Kode contoh

  1. Pemilik objek menghasilkan URL dengan tanda tangan untuk permintaan PUT.

    Penting

    Saat menghasilkan URL dengan tanda tangan untuk permintaan PUT, jika Anda menentukan header permintaan, Anda harus menyertakan header permintaan yang sama saat menggunakan URL dengan tanda tangan untuk memulai permintaan PUT. Jika tidak, permintaan akan gagal dan melaporkan kesalahan ketidakcocokan tanda tangan.

    using System.Text;
    using OSS = AlibabaCloud.OSS.V2;  // Buat alias untuk SDK Alibaba Cloud OSS untuk menyederhanakan penggunaan selanjutnya.
    
    var region = "cn-hangzhou";  // Diperlukan. Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou.
    var endpoint = null as string;  // Opsional. Tentukan titik akhir yang digunakan untuk mengakses OSS. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com.
    var bucket = "nama bucket Anda";  // Diperlukan. Nama bucket.
    var key = "kunci objek Anda";  // Diperlukan. Nama objek setelah diunggah ke OSS.
    
    // Muat konfigurasi default dari SDK OSS. Konfigurasi ini secara otomatis membaca informasi kredensial (seperti AccessKey) dari variabel lingkungan.
    var cfg = OSS.Configuration.LoadDefault();
    // Secara eksplisit konfigurasikan penggunaan variabel lingkungan untuk mendapatkan kredensial untuk verifikasi identitas. Format: OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET.
    cfg.CredentialsProvider = new OSS.Credentials.EnvironmentVariableCredentialsProvider();
    // Atur wilayah bucket dalam konfigurasi.
    cfg.Region = region;   
    // Jika titik akhir ditentukan, itu akan menimpa titik akhir default. 
    if(endpoint != null) 
    {
        cfg.Endpoint = endpoint;
    } 
    
    // Buat instans klien OSS menggunakan informasi konfigurasi.
    using var client = new OSS.Client(cfg); 
    // Panggil metode Presign untuk menghasilkan URL dengan tanda tangan.
    var result = client.Presign(new OSS.Models.PutObjectRequest()
    {
        Bucket = bucket,
        Key = key,
    });
    
    // Konten untuk diunggah.
    const string content = "hello oss!";
    // Gunakan HttpClient untuk mengunggah konten menggunakan URL dengan tanda tangan.
    using var hc = new HttpClient();
    var httpResult = await hc.PutAsync(result.Url, new ByteArrayContent(Encoding.UTF8.GetBytes(content)));
    
    Console.WriteLine("PutObject selesai");  // Cetak pesan yang menunjukkan bahwa operasi selesai.
    Console.WriteLine($"Kode Status: {httpResult.StatusCode}");  // Kode status HTTP dari tanggapan.
  2. Pengguna lain menggunakan URL dengan tanda tangan untuk permintaan PUT untuk mengunggah objek.

    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;
    
            // Ganti <signedUrl> dengan URL dengan tanda tangan. 
            URL signedUrl = new URL("<signedUrl>");
    
            // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 
            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("Kode status:"+response.getStatusLine().getStatusCode());
                if(response.getStatusLine().getStatusCode() == 200){
                    System.out.println("Objek diunggah menggunakan pustaka.");
                }
                System.out.println(response.toString());
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                response.close();
                httpClient.close();
            }
        }
    }       

    Go

    package main
    
    import (
    	"fmt"
    	"io"
    	"net/http"
    	"os"
    )
    
    func uploadFile(signedUrl, filePath string) error {
    	// Buka file lokal.
    	file, err := os.Open(filePath)
    	if err != nil {
    		return fmt.Errorf("Tidak dapat membuka file lokal: %w", err)
    	}
    	defer file.Close()
    
    	// Buat klien HTTP.
    	client := &http.Client{}
    
    	// Buat permintaan PUT.
    	req, err := http.NewRequest("PUT", signedUrl, file)
    	if err != nil {
    		return fmt.Errorf("Gagal membuat permintaan: %w", err)
    	}
    
    	// Kirim permintaan.
    	resp, err := client.Do(req)
    	if err != nil {
    		return fmt.Errorf("Gagal mengirim permintaan:: %w", err)
    	}
    	defer resp.Body.Close()
    
    	// Baca tanggapan.
    	body, err := io.ReadAll(resp.Body)
    	if err != nil {
    		return fmt.Errorf("Gagal membaca permintaan: %w", err)
    	}
    
    	fmt.Printf("Kode status: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Objek diunggah menggunakan pustaka.")
    	}
    	fmt.Println(string(body))
    
    	return nil
    }
    
    func main() {
    	// Ganti <signedUrl> dengan URL dengan tanda tangan. 
    	signedUrl := "<signedUrl>"
    
    	// Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 
    	filePath := "C:\\Users\\demo.txt"
    
    	err := uploadFile(signedUrl, filePath)
    	if err != nil {
    		fmt.Println("Terjadi kesalahan: ", err)
    	}
    }
    

    python

    import requests
    
    def upload_file(signed_url, file_path):
        try:
            # Buka file lokal yang ingin Anda unggah.
            with open(file_path, 'rb') as file:
                # Kirim permintaan PUT untuk mengunggah file lokal.
                response = requests.put(signed_url, data=file)
         
            print(f"Kode status: {response.status_code}")
            if response.status_code == 200:
                print("Objek diunggah menggunakan pustaka.")
            print(response.text)
     
        except Exception as e:
            print(f"Terjadi kesalahan: {e}")
    
    if __name__ == "__main__":
        # Ganti <signedUrl> dengan URL dengan tanda tangan yang dihasilkan. 
        signed_url = "<signedUrl>"
        
        # Tentukan jalur lengkap file lokal. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 
        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 {
            // Buat aliran baca.
            const fileStream = fs.createReadStream(filePath);
            
            // Kirim permintaan PUT untuk mengunggah file lokal.
            const response = await axios.put(signedUrl, fileStream, {
                headers: {
                    'Content-Type': 'application/octet-stream' // Tentukan parameter Content-Type.
                }
            });
    
            console.log(`Kode status: ${response.status}`);
            if (response.status === 200) {
                console.log("Objek diunggah menggunakan pustaka.");
            }
            console.log(response.data);
        } catch (error) {
            console.error(`Terjadi kesalahan: ${error.message}`);
        }
    }
    
    // Tentukan fungsi utama.
    (async () => {
        // Ganti <signedUrl> dengan URL dengan tanda tangan. 
        const signedUrl = '<signedUrl>';
        
        // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 
        const filePath = 'C:\\Users\\demo.txt';
    
        await uploadFile(signedUrl, filePath);
    })();

    browser.js

    Penting

    Saat mengunggah objek menggunakan Browser.js dan URL dengan tanda tangan, kesalahan 403 SignatureNotMatch yang menunjukkan ketidaksesuaian tanda tangan mungkin terjadi. Ini biasanya disebabkan oleh penyertaan otomatis header permintaan Content-Type oleh browser, yang tidak ditentukan saat URL dengan tanda tangan dihasilkan. Untuk mencegah kesalahan ini, pastikan header Content-Type ditentukan saat menghasilkan URL dengan tanda tangan.

    <!DOCTYPE html>
    <html lang="id">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Contoh Unggah File</title>
    </head>
    <body>
        <h1>Contoh Unggah File</h1>
    
        <! -- Pilih File -->
        <input type="file" id="fileInput" />
        <button id="uploadButton">Unggah File</button>
    
        <script>
            // Ganti <signedUrl> dengan URL dengan tanda tangan yang dihasilkan pada Langkah 1. 
            const signedUrl = "<signedUrl>"; 
    
    
            document.getElementById('uploadButton').addEventListener('click', async () => {
                const fileInput = document.getElementById('fileInput');
                const file = fileInput.files[0];
    
                if (!file) {
                    alert('Silakan pilih file untuk diunggah.');
                    return;
                }
    
                try {
                    await upload(file, signedUrl);
                    alert('File berhasil diunggah!');
                } catch (error) {
                    console.error('Kesalahan saat mengunggah:', error);
                    alert('Unggah gagal: ' + error.message);
                }
            });
    
            /**
             * Unggah file ke OSS.
             * @param {File} file - File yang akan diunggah.
             * @param {string} presignedUrl - URL dengan tanda tangan.
             */
            const upload = async (file, presignedUrl) => {
                const response = await fetch(presignedUrl, {
                    method: 'PUT',
                    body: file,  // Unggah seluruh file.
                });
    
                if (!response.ok) {
                    throw new Error(`Unggah gagal, status: ${response.status}`);
                }
    
                console.log('File berhasil diunggah');
            };
        </script>
    </body>
    </html>

    C#

    using System.Net.Http.Headers;
    
    // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 
    var filePath = "C:\\Users\\demo.txt";
    // Ganti <signedUrl> dengan URL dengan tanda tangan.
    var presignedUrl = "<signedUrl>";
    
    // Buat klien HTTP dan aliran file lokal.
    using var httpClient = new HttpClient(); 
    using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    using var content = new StreamContent(fileStream);
                
    // Buat permintaan PUT.
    var request = new HttpRequestMessage(HttpMethod.Put, presignedUrl);
    request.Content = content;
    
    // Kirim permintaan.
    var response = await httpClient.SendAsync(request);
    
    // Proses tanggapan.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Diunggah! Kode Status: {response.StatusCode}");
        Console.WriteLine("Header Tanggapan:");
        foreach (var header in response.Headers)
        {
            Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
        }
    }
    else
    {
        string responseContent = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"Unggah Gagal! Kode Status: {response.StatusCode}");
        Console.WriteLine("Isi tanggapan: " + 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) {
            // Tentukan URL dengan tanda tangan.
            curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str());
    
            // Setel metode permintaan ke PUT.
            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    
            // Buka file lokal.
            FILE *file = fopen(filePath.c_str(), "rb");
            if (!file) {
                std::cerr << "Tidak dapat membuka file: " << filePath << std::endl;
                return;
            }
    
            // Periksa ukuran file lokal.
            fseek(file, 0, SEEK_END);
            long fileSize = ftell(file);
            fseek(file, 0, SEEK_SET);
    
            // Tentukan ukuran file lokal.
            curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
    
            // Tentukan handle file input.
            curl_easy_setopt(curl, CURLOPT_READDATA, file);
    
            // Eksekusi permintaan.
            res = curl_easy_perform(curl);
    
            if (res != CURLE_OK) {
                std::cerr << "curl_easy_perform() gagal: " << curl_easy_strerror(res) << std::endl;
            } else {
                long httpCode = 0;
                curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
                std::cout << "Kode status: " << httpCode << std::endl;
    
                if (httpCode == 200) {
                    std::cout << "Objek diunggah menggunakan pustaka jaringan." << std::endl;
                }
            }
    
            // Tutup file lokal.
            fclose(file);
    
            // Bersihkan handle cURL.
            curl_easy_cleanup(curl);
        }
    
        curl_global_cleanup();
    }
    
    int main() {
        // Ganti <signedUrl> dengan URL dengan tanda tangan. 
        std::string signedUrl = "<signedUrl>";
    
        // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 
        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, "Kode status: " + responseCode);
    
                    if (responseCode == 200) {
                        Log.d(TAG, "Objek diunggah menggunakan pustaka.");
                    }
    
                    return "Objek diunggah. Kode status: " + responseCode;
    
                } catch (IOException e) {
                    e.printStackTrace();
                    return "Unggah gagal: " + 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();
            // Ganti <signedUrl> dengan URL dengan tanda tangan. 
            String signedUrl = "<signedUrl>";
            // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 
            String filePath = "C:\\Users\\demo.txt";
            activity.uploadFile(signedUrl, filePath);
        }
    }
    

Skenario

Menggunakan URL yang telah ditandatangani untuk mengunggah objek dengan header permintaan dan metadata kustom yang ditentukan

  1. Pemilik objek menghasilkan URL yang telah ditandatangani untuk permintaan PUT dengan header permintaan dan metadata kustom yang ditentukan.

    using System.Text;
    using OSS = AlibabaCloud.OSS.V2;  // Buat alias untuk SDK Alibaba Cloud OSS untuk menyederhanakan penggunaan selanjutnya.
    using System.Globalization;
    using System.Net.Http.Headers;
    
    var region = "cn-hangzhou";  // Diperlukan. Tentukan wilayah di mana bucket berada. Sebagai contoh, jika bucket berada di wilayah China (Hangzhou), atur wilayah ke cn-hangzhou.
    var endpoint = null as string;  // Opsional. Tentukan titik akhir yang digunakan untuk mengakses OSS. Sebagai contoh, jika bucket berada di wilayah China (Hangzhou), atur titik akhir ke https://oss-cn-hangzhou.aliyuncs.com.
    var bucket = "nama bucket Anda";  // Diperlukan. Nama bucket.
    var key = "kunci objek Anda";  // Diperlukan. Nama objek setelah diunggah ke OSS.
    
    // Muat konfigurasi default dari SDK OSS. Konfigurasi ini secara otomatis membaca informasi kredensial (seperti AccessKey) dari variabel lingkungan.
    var cfg = OSS.Configuration.LoadDefault();
    // Secara eksplisit konfigurasikan penggunaan variabel lingkungan untuk mendapatkan kredensial untuk verifikasi identitas. Format: OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET.
    cfg.CredentialsProvider = new OSS.Credentials.EnvironmentVariableCredentialsProvider();
    // Atur wilayah bucket dalam konfigurasi.
    cfg.Region = region;   
    // Jika titik akhir ditentukan, itu akan menimpa titik akhir default. 
    if(endpoint != null) 
    { 
        cfg.Endpoint = endpoint;
    } 
    
    // Buat instans klien OSS menggunakan informasi konfigurasi.
    using var client = new OSS.Client(cfg); 
    // Panggil metode Presign untuk mendapatkan URL unggah yang telah ditandatangani.
    var result = client.Presign(new OSS.Models.PutObjectRequest()
        {
            Bucket = bucket,
            Key = key,
            StorageClass = "Standard",         // Atur kelas penyimpanan ke Standard.
            ContentType = "text/plain; charset=utf8",    // Atur tipe konten.
            Metadata = new Dictionary<string, string>() {
                { "key1", "value1" },    // Tambahkan metadata kustom.
                { "key2", "value2" }
            }
        }
    );
    
    // Buat instans klien HTTP.
    using var hc = new HttpClient();
    
    // Siapkan konten yang akan diunggah.
    var content1 = "hello oss";
    var requestMessage = new HttpRequestMessage(HttpMethod.Put, new Uri(result.Url));
    requestMessage.Content = new ByteArrayContent(Encoding.UTF8.GetBytes(content1));
    
    // Tambahkan header HTTP yang termasuk dalam URL yang telah ditandatangani.
    foreach (var item in result.SignedHeaders!)
    {
        switch (item.Key.ToLower())
        {
            case "content-disposition":
                // Atur disposisi konten.
                requestMessage.Content.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse(item.Value);
                break;
            case "content-encoding":
                // Atur pengkodean konten.
                requestMessage.Content.Headers.ContentEncoding.Add(item.Value);
                break;
            case "content-language":
                // Atur bahasa konten.
                requestMessage.Content.Headers.ContentLanguage.Add(item.Value);
                break;
            case "content-type":
                // Atur tipe konten.
                requestMessage.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(item.Value);
                break;
            case "content-md5":
                // Atur hash MD5 dari konten.
                requestMessage.Content.Headers.ContentMD5 = Convert.FromBase64String(item.Value);
                break;
            case "content-length":
                // Atur panjang konten.
                requestMessage.Content.Headers.ContentLength = Convert.ToInt64(item.Value);
                break;
            case "expires":
                // Atur waktu kedaluwarsa konten.
                if (DateTime.TryParse(
                        item.Value,
                        CultureInfo.InvariantCulture,
                        DateTimeStyles.None,
                        out var expires
                    ))
                    requestMessage.Content.Headers.Expires = expires;
                break;
            default:
                // Tambahkan informasi header umum lainnya.
                requestMessage.Headers.Add(item.Key, item.Value);
                break;
        }
    }
    // Kirim permintaan HTTP dan dapatkan tanggapan.
    var httpResult = await hc.SendAsync(requestMessage);
    
    Console.WriteLine("PutObject selesai");  // Cetak pesan yang menunjukkan bahwa operasi selesai.
    Console.WriteLine($"Kode Status: {httpResult.StatusCode}");  // Kode status HTTP dari tanggapan.
  2. Pengguna lain menggunakan URL yang telah ditandatangani untuk permintaan PUT untuk mengunggah objek.

    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

    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;
    
            // Ganti <signedUrl> dengan URL yang telah ditandatangani. 
            URL signedUrl = new URL("<signedUrl>");
    
            // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal akan diunggah dari jalur proyek tempat program sampel milik. 
            String pathName = "C:\\Users\\demo.txt";
    
            // Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang telah ditandatangani dibuat. 
            Map<String, String> headers = new HashMap<String, String>();
            // Tentukan kelas penyimpanan objek. 
            headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
            // Tentukan tipe konten. 
            headers.put(OSSHeaders.CONTENT_TYPE, "text/plain;charset=utf8");
    
            // Tentukan metadata pengguna. Pastikan metadata pengguna di sini sama dengan metadata pengguna yang ditentukan saat URL yang telah ditandatangani dibuat. 
            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);
                // Jika Anda mengonfigurasi header seperti metadata pengguna dan kelas penyimpanan saat URL yang telah ditandatangani dibuat, header tersebut harus dikirim ke server saat URL yang telah ditandatangani digunakan untuk mengunggah file. Jika header yang dikirim ke server untuk perhitungan tanda tangan berbeda dari header yang ditentukan saat URL yang telah ditandatangani dibuat, kesalahan tanda tangan dilaporkan. 
                for(Map.Entry header: headers.entrySet()){
                    put.addHeader(header.getKey().toString(),header.getValue().toString());
                }
                for(Map.Entry meta: userMetadata.entrySet()){
                    // Jika metadata pengguna ditentukan, SDK menambahkan awalan "x-oss-meta-" ke kunci metadata pengguna. Jika Anda menggunakan metode lain untuk mengunggah file, pastikan bahwa awalan "x-oss-meta-" juga ditambahkan ke kunci metadata pengguna. 
                    put.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString());
                }
    
                httpClient = HttpClients.createDefault();
    
                response = httpClient.execute(put);
    
                System.out.println("Kode status unggah: "+response.getStatusLine().getStatusCode());
                if(response.getStatusLine().getStatusCode() == 200){
                    System.out.println("Objek diunggah menggunakan pustaka.");
                }
                System.out.println(response.toString());
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                response.close();
                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 {
    	// Buka file lokal.
    	file, err := os.Open(filePath)
    	if err != nil {
    		return err
    	}
    	defer file.Close()
    
    	// Baca konten objek.
    	fileBytes, err := ioutil.ReadAll(file)
    	if err != nil {
    		return err
    	}
    
    	// Buat permintaan.
    	req, err := http.NewRequest("PUT", signedUrl, bytes.NewBuffer(fileBytes))
    	if err != nil {
    		return err
    	}
    
    	// Tentukan header permintaan.
    	for key, value := range headers {
    		req.Header.Set(key, value)
    	}
    
    	// Tentukan metadata pengguna.
    	for key, value := range metadata {
    		req.Header.Set(fmt.Sprintf("x-oss-meta-%s", key), value)
    	}
    
    	// Kirim permintaan.
    	client := &http.Client{}
    	resp, err := client.Do(req)
    	if err != nil {
    		return err
    	}
    	defer resp.Body.Close()
    
    	// Proses tanggapan.
    	fmt.Printf("Kode status: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Objek diunggah menggunakan pustaka.")
    	} else {
    		fmt.Println("Unggah gagal")
    	}
    	body, _ := ioutil.ReadAll(resp.Body)
    	fmt.Println(string(body))
    
    	return nil
    }
    
    func main() {
    	// Ganti <signedUrl> dengan URL yang telah ditandatangani. 
    	signedUrl := "<signedUrl>"
    
    	// Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal akan diunggah dari jalur proyek tempat program sampel milik. 
    	filePath := "C:\\Users\\demo.txt"
    
    	// Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang telah ditandatangani dibuat. 
    	headers := map[string]string{
    		"Content-Type": "text/plain;charset=utf8",
    		"x-oss-storage-class": "Standard",
    	}
    
    	// Tentukan metadata pengguna. Pastikan metadata pengguna di sini sama dengan metadata pengguna yang ditentukan saat URL yang telah ditandatangani dibuat. 
    	metadata := map[string]string{
    		"key1": "value1",
    		"key2": "value2",
    	}
    
    	err := uploadFile(signedUrl, filePath, headers, metadata)
    	if err != nil {
    		fmt.Printf("Terjadi kesalahan: %v\n", err)
    	}
    }
    

    Python

    import requests
    from requests.auth import HTTPBasicAuth
    import os
    
    def upload_file(signed_url, file_path, headers=None, metadata=None):
        """
        Gunakan URL yang telah ditandatangani untuk mengunggah objek ke OSS. 
    
        :param signed_url: URL yang telah ditandatangani. 
        :param file_path: jalur lengkap file lokal yang ingin Anda unggah. 
        :param headers: header permintaan. Parameter ini opsional. 
        :param metadata: metadata pengguna. Parameter ini opsional. 
        :return: None
        """
        if not headers:
            headers = {}
        if not metadata:
            metadata = {}
    
        # Tambahkan awalan x-oss-meta- ke kunci metadata.
        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"Kode status: {response.status_code}")
                if response.status_code == 200:
                    print("Objek diunggah menggunakan pustaka.")
                else:
                    print("Unggah gagal.")
                print(response.text)
        except Exception as e:
            print(f"Terjadi kesalahan: {e}")
    
    if __name__ == "__main__":
        # Ganti <signedUrl> dengan URL yang telah ditandatangani yang dihasilkan. 
        signed_url = "<signedUrl>"
       
        # Tentukan jalur lengkap file lokal. Secara default, jika Anda tidak menentukan jalur lengkap file lokal, file lokal akan diunggah dari direktori tempat skrip disimpan. 
        file_path = "C:\\Users\\demo.txt"
    
        # Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang telah ditandatangani dibuat. 
        headers = {
             "Content-Type": "text/plain;charset=utf8",
             "x-oss-storage-class": "Standard"
        }
    
        # Tentukan metadata pengguna. Pastikan metadata pengguna sama dengan metadata pengguna yang ditentukan saat URL yang telah ditandatangani dibuat. 
        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 {
            // Tambahkan awalan x-oss-meta- ke kunci metadata.
            for (const [key, value] of Object.entries(metadata)) {
                headers[`x-oss-meta-${key}`] = value;
            }
    
            // Buat aliran baca.
            const fileStream = fs.createReadStream(filePath);
    
            // Kirim permintaan PUT.
            const response = await axios.put(signedUrl, fileStream, {
                headers: headers
            });
    
            console.log(`Kode status: ${response.status}`);
            if (response.status === 200) {
                console.log("Objek diunggah menggunakan pustaka.");
            } else {
                console.log("Unggah gagal.");
            }
            console.log(response.data);
        } catch (error) {
            console.error(`Terjadi kesalahan: ${error.message}`);
        }
    }
    
    // Tentukan fungsi utama.
    (async () => {
        // Ganti <signedUrl> dengan URL yang telah ditandatangani. 
        const signedUrl = "<signedUrl>";
    
        // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Secara default, jika Anda tidak menentukan jalur lengkap file lokal, file lokal akan diunggah dari direktori tempat skrip disimpan. 
        const filePath = "C:\\Users\\demo.txt";
    
        // Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang telah ditandatangani dibuat. 
        const headers = {
             "Content-Type": "text/plain;charset=utf8",
             "x-oss-storage-class": "Standard"
        };
    
        // Tentukan metadata pengguna. Pastikan metadata pengguna di sini sama dengan metadata pengguna yang ditentukan saat URL yang telah ditandatangani dibuat. 
        const metadata = {
             "key1": "value1",
             "key2": "value2"
        };
    
        await uploadFile(signedUrl, filePath, headers, metadata);
    })();
    

    Browser.js

    Penting

    Saat menggunakan kode Browser.js untuk mengunggah objek berdasarkan URL yang telah ditandatangani, Anda mungkin mengalami kesalahan 403 yang menunjukkan ketidaksesuaian tanda tangan. Kesalahan ini muncul dari kegagalan verifikasi tanda tangan, yang terjadi karena browser secara otomatis menambahkan header permintaan Content-Type, elemen yang tidak ditentukan saat URL yang telah ditandatangani dibuat. Untuk menyelesaikan kesalahan, Anda harus menentukan header Content-Type saat menghasilkan URL yang telah ditandatangani yang diharapkan digunakan dalam kode Browser.js untuk mengunggah data ke OSS.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Contoh Unggah File</title>
    </head>
    <body>
        <h1>Contoh Unggah File</h1>
    
        <input type="file" id="fileInput" />
        <button id="uploadButton">Unggah File</button>
    
        <script>
            // Ganti <signedUrl> dengan URL yang telah ditandatangani sebenarnya.
            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('Kesalahan selama unggah:', error);
                        alert('Unggah gagal: ' + error.message);
                    }
                } else {
                    alert('Silakan pilih file untuk diunggah.');
                }
            });
    
            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(`Unggah gagal, status: ${response.status}`);
                }
    
                alert('File berhasil diunggah');
                console.log('File berhasil diunggah');
            };
        </script>
    </body>
    </html>

    C#

    using System.Net.Http.Headers;
    
    // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal akan diunggah dari jalur proyek tempat program sampel milik. 
    var filePath = "C:\\Users\\demo.txt";
    // Ganti <signedUrl> dengan URL yang telah ditandatangani.
    var presignedUrl = "<signedUrl>";
    
    // Buat klien HTTP dan aliran file lokal.
    using var httpClient = new HttpClient(); 
    using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    using var content = new StreamContent(fileStream);
                
    // Buat permintaan PUT.
    var request = new HttpRequestMessage(HttpMethod.Put, presignedUrl);
    request.Content = content;
    
    // Jika Anda mengonfigurasi header seperti metadata pengguna dan kelas penyimpanan saat URL yang telah ditandatangani dibuat, header tersebut harus dikirim ke server saat URL yang telah ditandatangani digunakan untuk mengunggah file.
    // Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang telah ditandatangani dibuat.
    request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain") { CharSet = "utf8" };  // Tentukan tipe konten.      
    // Tentukan metadata pengguna. Pastikan metadata pengguna sama dengan metadata pengguna yang ditentukan saat URL yang telah ditandatangani dibuat.
    request.Content.Headers.Add("x-oss-meta-key1", "value1");
    request.Content.Headers.Add("x-oss-meta-key2", "value2");
    // Tentukan kelas penyimpanan objek.
    request.Content.Headers.Add("x-oss-storage-class", "Standard");
    
    // Keluarkan header permintaan.
    Console.WriteLine("Header Permintaan:");
    foreach (var header in request.Content.Headers)
    {
        Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
    }
    
    // Kirim permintaan.
    var response = await httpClient.SendAsync(request);
    
    // Proses tanggapan.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Diunggah! Kode Status: {response.StatusCode}");
        Console.WriteLine("Header Tanggapan:");
        foreach (var header in response.Headers)
        {
            Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
        }
    }
    else
    {
        string responseContent = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"Unggah gagal! Kode Status: {response.StatusCode}");
        Console.WriteLine("Isi Tanggapan: " + responseContent);
    }

    C++

    #include <iostream>
    #include <fstream>
    #include <curl/curl.h>
    #include <map>
    #include <string>
    
    // Tentukan fungsi callback yang digunakan untuk memproses respons HTTP.
    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) {
            // Tentukan URL yang telah ditandatangani.
            curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str());
    
            // Atur metode permintaan ke PUT.
            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    
            // Buka file lokal.
            FILE* file = fopen(filePath.c_str(), "rb");
            if (!file) {
                std::cerr << "Tidak dapat membuka file: " << filePath << std::endl;
                return;
            }
    
            // Tentukan ukuran file lokal.
            fseek(file, 0, SEEK_END);
            long fileSize = ftell(file);
            rewind(file);
    
            // Konfigurasikan callback pembacaan file.
            curl_easy_setopt(curl, CURLOPT_READDATA, file);
            curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
    
            // Tentukan header permintaan.
            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);
    
            // Tentukan fungsi callback yang digunakan untuk memproses respons.
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
    
            // Eksekusi permintaan.
            res = curl_easy_perform(curl);
    
            // Periksa respons.
            if (res != CURLE_OK) {
                std::cerr << "curl_easy_perform() gagal: " << curl_easy_strerror(res) << std::endl;
            } else {
                long responseCode;
                curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
                std::cout << "Kode status: " << responseCode << std::endl;
                if (responseCode == 200) {
                    std::cout << "Objek diunggah menggunakan pustaka jaringan." << std::endl;
                } else {
                    std::cout << "Unggah gagal." << std::endl;
                }
                std::cout << readBuffer << std::endl;
            }
    
            // Bersihkan handle cURL.
            fclose(file);
            curl_slist_free_all(chunk);
            curl_easy_cleanup(curl);
        }
    
        curl_global_cleanup();
    }
    
    int main() {
        // Ganti <signedUrl> dengan URL yang telah ditandatangani. 
        std::string signedUrl = "<signedUrl>";
    
        // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal akan diunggah dari jalur proyek tempat program sampel milik. 
        std::string filePath = "C:\\Users\\demo.txt";
    
        // Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang telah ditandatangani dibuat. 
        std::map<std::string, std::string> headers = {
             {"Content-Type", "text/plain;charset=utf8"},
             {"x-oss-storage-class", "Standard"}
        };
    
        // Tentukan metadata pengguna. Pastikan metadata pengguna di sini sama dengan metadata pengguna yang ditentukan saat URL yang telah ditandatangani dibuat. 
        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);
    
            // Ganti <signedUrl> dengan URL yang telah ditandatangani. 
            String signedUrl = "<signedUrl>";
    
            // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal akan diunggah dari jalur proyek tempat program sampel milik. 
            String pathName = "/storage/emulated/0/demo.txt";
    
            // Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang telah ditandatangani dibuat. 
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "text/plain;charset=utf8");
            headers.put("x-oss-storage-class", "Standard");
    
            // Tentukan metadata pengguna. Pastikan metadata pengguna di sini sama dengan metadata pengguna yang ditentukan saat URL yang telah ditandatangani dibuat. 
            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);
    
                    // Tentukan header permintaan.
                    for (Entry<String, String> header : headers.entrySet()) {
                        connection.setRequestProperty(header.getKey(), header.getValue());
                    }
    
                    // Tentukan metadata pengguna.
                    for (Entry<String, String> meta : userMetadata.entrySet()) {
                        connection.setRequestProperty("x-oss-meta-" + meta.getKey(), meta.getValue());
                    }
    
                    // Baca file lokal.
                    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();
    
                    // Dapatkan respons.
                    int responseCode = connection.getResponseCode();
                    Log.d(TAG, "Kode status: " + responseCode);
                    if (responseCode == 200) {
                        Log.d(TAG, "Objek diunggah menggunakan pustaka.");
                    } else {
                        Log.d(TAG, "Unggah gagal");
                    }
    
                    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, "Objek diunggah", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SignUrlUploadActivity.this, "Unggah gagal", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
    

Menggunakan URL yang telah ditandatangani untuk mengunggah objek menggunakan unggah multipart

Untuk mengunggah objek menggunakan URL yang telah ditandatangani dan unggah multipart, Anda harus mengonfigurasi ukuran bagian dan menghasilkan URL yang telah ditandatangani untuk setiap bagian. Contoh kode berikut memberikan ilustrasi:

using OSS = AlibabaCloud.OSS.V2;  // Buat alias untuk SDK Alibaba Cloud OSS untuk menyederhanakan penggunaan selanjutnya.

var region = "cn-hangzhou";  // Diperlukan. Tentukan wilayah di mana bucket berada. Sebagai contoh, jika bucket berada di wilayah China (Hangzhou), atur wilayah ke cn-hangzhou.
var endpoint = null as string;  // Opsional. Tentukan titik akhir yang digunakan untuk mengakses OSS. Sebagai contoh, jika bucket berada di wilayah China (Hangzhou), atur titik akhir ke https://oss-cn-hangzhou.aliyuncs.com.
var bucket = "bucket nama Anda";  // Diperlukan. Nama bucket.
var key = "kunci objek Anda";  // Diperlukan. Nama objek yang akan diunggah.
var partSize = 512*1024;  // Diperlukan. Ukuran setiap bagian untuk setiap unggah. Dalam contoh ini, ukuran bagian adalah 512 KB.
var filePath = "jalur file";  // Diperlukan. Jalur objek yang akan diunggah.

// Muat konfigurasi default dari SDK OSS. Konfigurasi ini secara otomatis membaca informasi kredensial (seperti AccessKey) dari variabel lingkungan.
var cfg = OSS.Configuration.LoadDefault();
// Secara eksplisit konfigurasikan penggunaan variabel lingkungan untuk mendapatkan kredensial untuk verifikasi identitas. Format: OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET.
cfg.CredentialsProvider = new OSS.Credentials.EnvironmentVariableCredentialsProvider();
// Atur wilayah bucket dalam konfigurasi.
cfg.Region = region;   
// Jika titik akhir ditentukan, itu akan menimpa titik akhir default. 
if(endpoint != null) 
{
    cfg.Endpoint = endpoint;
} 

// Buat instans klien OSS menggunakan informasi konfigurasi.
using var client = new OSS.Client(cfg); 

// Mulai unggah multipart.
var initResult = await client.InitiateMultipartUploadAsync(new()
{
    Bucket = bucket,
    Key = key
});

// Buka file yang akan diunggah.
using var hc = new HttpClient();
using var file = File.OpenRead(filePath);
long fileSize = file.Length;
long partNumber = 1;

// Unggah file dalam bagian-bagian.
for (long offset = 0; offset < fileSize; offset += partSize)
{
    // Hitung ukuran bagian saat ini.
    var size = Math.Min(partSize, fileSize - offset);

    // Hasilkan URL yang telah ditandatangani untuk unggah langsung dari klien.
    var presignResult = client.Presign(new OSS.Models.UploadPartRequest
    {
        Bucket = bucket,
        Key = key,
        PartNumber = partNumber,
        UploadId = initResult.UploadId,
        Body = new OSS.IO.BoundedStream(file, offset, size)
    });

    // Gunakan URL yang telah ditandatangani untuk mengirim permintaan PUT guna mengunggah bagian tersebut.
    var httpResult = await hc.PutAsync(
        presignResult.Url,
        new StreamContent(new OSS.IO.BoundedStream(file, offset, size))
    );

    // Periksa apakah unggah berhasil.
    if (!httpResult.IsSuccessStatusCode)
    {
        throw new Exception("gagal mengunggah bagian");
    }
    partNumber++;
}

// Daftarkan semua bagian yang telah diunggah.
var uploadParts = new List<OSS.Models.UploadPart>();
var paginator = client.ListPartsPaginator(new ()
{
    Bucket = bucket,
    Key = key,
    UploadId = initResult.UploadId,
});

// Dapatkan semua informasi bagian berdasarkan halaman.
await foreach (var page in paginator.IterPageAsync())
{
    foreach (var part in page.Parts ?? [])
    {
        uploadParts.Add(new() { PartNumber = part.PartNumber, ETag = part.ETag });
    }
}

// Urutkan bagian berdasarkan nomor bagian.
uploadParts.Sort((left, right) => { return (left.PartNumber > right.PartNumber) ? 1 : -1; });

// Selesaikan unggah multipart.
var cmResult = await client.CompleteMultipartUploadAsync(new()
{
    Bucket = bucket,
    Key = key,
    UploadId = initResult.UploadId,
    CompleteMultipartUpload = new()
    {
        Parts = uploadParts
    }
});

// Cetak hasil unggah.
Console.WriteLine("MultipartUpload selesai");  // Pesan yang menunjukkan bahwa operasi selesai.
Console.WriteLine($"Kode Status: {cmResult.StatusCode}");  // Kode status HTTP.
Console.WriteLine($"ID Permintaan: {cmResult.RequestId}");  // ID permintaan, yang digunakan oleh Alibaba Cloud untuk pemecahan masalah.
Console.WriteLine("Header Tanggapan:");  // Informasi header tanggapan.
cmResult.Headers.ToList().ForEach(x => Console.WriteLine(x.Key + " : " + x.Value));  // Lintasi dan cetak semua header tanggapan.

FAQ

Jika saya menggunakan tanda tangan sementara untuk mengunggah objek dan tanda tangan tersebut kedaluwarsa selama pengunggahan, apakah pengunggahan gagal?

Pengunggahan akan berhasil.

Tanda tangan diverifikasi saat permintaan pengunggahan dimulai. Pengunggahan dapat dilanjutkan jika URL valid pada saat itu. Jika Anda menggunakan token sementara, periode validitas dari presigned URL adalah yang lebih pendek antara periode validitas token dan waktu kedaluwarsa yang ditentukan dalam URL.

Jika saya tidak menetapkan header permintaan dan metadata kustom saat saya membuat URL, apakah saya perlu mengonfigurasinya saat menggunakan URL untuk pengunggahan?

Tidak, Anda tidak perlu.

Header permintaan dan metadata kustom adalah parameter opsional. Jika Anda tidak menetapkan header permintaan dan metadata kustom, Anda dapat menghapus kode terkait dari contoh kode.

Referensi

Untuk kode sampel lengkap yang digunakan untuk mengunggah objek menggunakan URL yang ditandatangani, lihat PresignPutObject.cs.