全部产品
Search
文档中心

Object Storage Service:Gunakan URL yang ditandatangani untuk mengunggah objek menggunakan OSS SDK untuk Python 2.0

更新时间:Aug 13, 2025

Secara default, daftar kontrol akses (ACL) dari sebuah objek Object Storage Service (OSS) di dalam bucket bersifat pribadi. Hanya pemilik objek yang memiliki izin untuk mengunggah objek ke bucket. Anda dapat menggunakan OSS SDK untuk Python untuk menghasilkan URL yang ditandatangani dan membagikan URL tersebut dengan pengguna untuk mengizinkan mereka mengunggah objek. Saat menghasilkan URL yang ditandatangani, Anda dapat menentukan periode validitas untuk membatasi jangka waktu pengguna dapat mengunggah objek. Selama periode validitas, pengguna dapat menggunakan URL tersebut untuk mengunggah objek berkali-kali. Jika objek diunggah berkali-kali, objek sebelumnya mungkin tertimpa. Setelah periode validitas berakhir, pengguna tidak dapat lagi menggunakan URL tersebut untuk mengunggah objek, dan Anda harus menghasilkan URL baru.

Catatan Penggunaan

  • Kode contoh dalam topik ini menggunakan ID wilayah cn-hangzhou dari Wilayah Hangzhou, Tiongkok. Secara default, titik akhir publik digunakan untuk mengakses sumber daya di bucket. Jika Anda ingin mengakses sumber daya di bucket menggunakan layanan Alibaba Cloud lainnya di wilayah yang sama dengan bucket tersebut, gunakan titik akhir internal. Untuk informasi lebih lanjut tentang wilayah dan titik akhir OSS, lihat Wilayah dan Titik Akhir.

  • Anda tidak memerlukan izin khusus untuk menghasilkan URL yang ditandatangani. Namun, untuk mengizinkan pihak ketiga menggunakan URL yang ditandatangani untuk mengunggah objek, Anda harus memiliki izin oss:PutObject. Untuk informasi lebih lanjut, lihat Memberikan Izin kepada Pengguna RAM Menggunakan Kebijakan Kustom.

  • Dalam topik ini, URL yang ditandatangani mencakup tanda tangan V4 dengan periode validitas hingga tujuh hari. Untuk informasi lebih lanjut, lihat (Direkomendasikan) Tanda Tangan V4 dalam URL yang Ditandatangani.

Proses

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

Metode

Anda dapat memanggil operasi tertentu untuk menghasilkan URL yang ditandatangani dan menggunakan URL tersebut untuk memberikan izin akses sementara pada objek di bucket. URL yang ditandatangani dapat digunakan beberapa kali sebelum kedaluwarsa.

Sintaks:

presign(request: PutObjectRequest, **kwargs) → PresignResult

Parameter Permintaan

Parameter

Tipe

Deskripsi

request

PutObjectRequest

Operasi API yang digunakan untuk menghasilkan URL yang ditandatangani. Untuk informasi lebih lanjut, lihat Client.presign.

expires

datetime.timedelta

Periode validitas URL yang ditandatangani. Ini adalah parameter opsional. Misalnya, jika Anda ingin menetapkan periode validitas menjadi 30 menit, atur expires menjadi 30 * time.Minute. Jika Anda tidak menentukan parameter ini, URL yang ditandatangani menggunakan nilai default, yaitu 15 menit.

expiration

datetime.datetime

Waktu kedaluwarsa absolut URL yang ditandatangani. Ini adalah parameter opsional.

Penting

Jika Anda menggunakan algoritma tanda tangan V4, periode validitas bisa mencapai tujuh hari. Jika Anda menentukan kedua Expiration dan Expires, Expiration akan didahulukan.

Parameter Tanggapan

Tipe

Deskripsi

PresignResult

Hasil yang dikembalikan, termasuk URL yang ditandatangani, metode HTTP, waktu kedaluwarsa, dan header permintaan yang ditentukan dalam permintaan. Untuk informasi lebih lanjut, lihat PresignResult.

Parameter tanggapan PresignResult

Parameter

Tipe

Deskripsi

method

str

Metode HTTP, yang sesuai dengan operasi API. Sebagai contoh, metode HTTP dari operasi PutObject adalah PUT.

url

str

URL yang ditandatangani.

expiration

datetime

Waktu kedaluwarsa URL yang ditandatangani.

signed_headers

MutableMapping

Header yang ditandatangani yang ditentukan dalam permintaan. Sebagai contoh, jika Content-Type ditentukan, informasi tentang Content-Type dikembalikan.

Untuk informasi lebih lanjut tentang metode presign, kunjungi presign.

Kode Contoh

  1. Hasilkan URL yang ditandatangani untuk mengizinkan permintaan HTTP PUT.

    Penting

    Jika Anda menentukan header permintaan saat menghasilkan URL yang ditandatangani untuk permintaan HTTP PUT, pastikan bahwa header permintaan tersebut disertakan dalam permintaan PUT yang dimulai menggunakan URL tersebut. Hal ini mencegah kegagalan permintaan dan kesalahan tanda tangan.

    import argparse
    import requests
    import alibabacloud_oss_v2 as oss
    
    from datetime import datetime, timedelta
    
    # Buat parser parameter baris perintah dan jelaskan tujuan skrip. Contoh ini menjelaskan cara menghasilkan URL yang ditandatangani yang mengizinkan permintaan HTTP PUT.
    parser = argparse.ArgumentParser(description="contoh presign put object")
    
    # Tentukan parameter baris perintah, termasuk wilayah, nama bucket, endpoint, dan nama objek yang diperlukan.
    parser.add_argument('--region', help='Wilayah tempat bucket berada.', required=True)
    parser.add_argument('--bucket', help='Nama bucket.', required=True)
    parser.add_argument('--endpoint', help='Nama domain yang dapat digunakan layanan lain untuk mengakses OSS')
    parser.add_argument('--key', help='Nama objek.', required=True)
    
    def main():
        # Parsing parameter baris perintah untuk mendapatkan nilai yang ditentukan oleh pengguna.
        args = parser.parse_args()
    
        # Dapatkan kredensial akses dari variabel lingkungan untuk otentikasi.
        credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    
        # Gunakan konfigurasi default SDK untuk membuat objek konfigurasi dan tentukan penyedia kredensial.
        cfg = oss.config.load_default()
        cfg.credentials_provider = credentials_provider
    
        # Tentukan atribut wilayah objek konfigurasi berdasarkan parameter baris perintah yang ditentukan oleh pengguna.
        cfg.region = args.region
    
        # Jika endpoint kustom disediakan, modifikasi parameter endpoint dalam objek konfigurasi.
        if args.endpoint is not None:
            cfg.endpoint = args.endpoint
    
        # Gunakan konfigurasi di atas untuk menginisialisasi instance OSSClient dan izinkan instance tersebut berinteraksi dengan OSS.
        client = oss.Client(cfg)
    
        # Kirim permintaan untuk memulai permintaan PUT dan hasilkan URL yang ditandatangani untuk objek yang ditentukan.
        pre_result = client.presign(oss.PutObjectRequest(
            bucket=args.bucket, # Nama bucket.
            key=args.key, # Nama objek.
        ),expires=timedelta(seconds=3600)) # Tentukan periode validitas permintaan. Dalam contoh ini, periode validitas diatur menjadi 3.600 detik.
    
        # Tampilkan metode, waktu kedaluwarsa, dan URL yang ditandatangani yang ditentukan dalam permintaan untuk memeriksa validitas URL yang ditandatangani.
        print(f'metode: {pre_result.method},'
              f' kedaluwarsa: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},'
              f' url: {pre_result.url}'
              )
    
        # Tampilkan header yang ditandatangani dalam permintaan, yang disertakan dalam header HTTP saat permintaan dikirim.
        for key, value in pre_result.signed_headers.items():
            print(f'header yang ditandatangani kunci: {key}, header yang ditandatangani nilai: {value}')
    
    # Panggil fungsi utama untuk memulai logika pemrosesan saat skrip dijalankan langsung.
    if __name__ == "__main__":
        main() # Tentukan titik masuk dalam fungsi skrip. Alur program kontrol dimulai di sini.
  2. Gunakan URL yang ditandatangani 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 otorisasi.
            URL signedUrl = new URL("<signedUrl>");
    
            // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara 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("Kode status yang dikembalikan:"+response.getStatusLine().getStatusCode());
                if(response.getStatusLine().getStatusCode() == 200){
                    System.out.println("Berhasil diunggah menggunakan library jaringan.");
                }
                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.
    	file, err := os.Open(filePath)
    	if err != nil {
    		return fmt.Errorf("Gagal membuka file: %w", err)
    	}
    	defer file.Close()
    
    	// Buat klien HTTP baru.
    	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 tanggapan: %w", err)
    	}
    
    	fmt.Printf("Kode status yang dikembalikan: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Berhasil diunggah menggunakan library jaringan.")
    	}
    	fmt.Println(string(body))
    
    	return nil
    }
    
    func main() {
    	// Ganti <signedUrl> dengan URL otorisasi.
    	signedUrl := "<signedUrl>"
    
    	// Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
    	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.
            with open(file_path, 'rb') as file:
                # Kirim permintaan PUT untuk mengunggah file.
                response = requests.put(signed_url, data=file)
         
            print(f"Kode status yang dikembalikan: {response.status_code}")
            if response.status_code == 200:
                print("Berhasil diunggah menggunakan library jaringan.")
            print(response.text)
     
        except Exception as e:
            print(f"Terjadi kesalahan: {e}")
    
    if __name__ == "__main__":
        # Ganti <signedUrl> dengan URL otorisasi.
        signed_url = "<signedUrl>"
        
        # Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
        file_path = "C:\\Users\\demo.txt"
    
        upload_file(signed_url, file_path)
    

    Node.js

    const fs = require('fs');
    const axios = require('axios');
    
    async function uploadFile(signedUrl, filePath) {
        try {
            // Buat aliran baca.
            const fileStream = fs.createReadStream(filePath);
            
            // Kirim permintaan PUT untuk mengunggah file.
            const response = await axios.put(signedUrl, fileStream, {
                headers: {
                    'Content-Type': 'application/octet-stream' // Sesuaikan Content-Type berdasarkan kebutuhan Anda.
                }
            });
    
            console.log(`Kode status yang dikembalikan: ${response.status}`);
            if (response.status === 200) {
                console.log('Berhasil diunggah menggunakan library jaringan.');
            }
            console.log(response.data);
        } catch (error) {
            console.error(`Terjadi kesalahan: ${error.message}`);
        }
    }
    
    // Fungsi utama.
    (async () => {
        // Ganti <signedUrl> dengan URL otorisasi.
        const signedUrl = '<signedUrl>';
        
        // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
        const filePath = 'C:\\Users\\demo.txt';
    
        await uploadFile(signedUrl, filePath);
    })();

    browser.js

    Penting

    Jika Anda menggunakan Browser.js untuk mengunggah file dan mengalami kesalahan 403 SignatureDoesNotMatch, kesalahan ini biasanya terjadi karena browser secara otomatis menambahkan header permintaan Content-Type. Jika header ini tidak ditentukan saat URL yang ditandatangani dihasilkan, verifikasi tanda tangan gagal. Untuk menyelesaikan masalah ini, Anda harus menentukan header permintaan Content-Type saat menghasilkan URL yang ditandatangani.

    <!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>
    
        <!-- Pilih file -->
        <input type="file" id="fileInput" />
        <button id="uploadButton">Unggah File</button>
    
        <script>
            // Ganti ini dengan URL yang ditandatangani yang dihasilkan di 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 unggah:', error);
                    alert('Unggah gagal: ' + error.message);
                }
            });
    
            /**
             * Unggah file ke OSS.
             * @param {File} file - File yang akan diunggah.
             * @param {string} presignedUrl - URL yang ditandatangani.
             */
            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. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
    var filePath = "C:\\Users\\demo.txt";
    // Ganti <signedUrl> dengan URL otorisasi.
    var presignedUrl = "<signedUrl>";
    
    // Buat klien HTTP dan buka 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($"Berhasil 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) {
            // Atur URL.
            curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str());
    
            // Atur metode permintaan ke PUT.
            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    
            // Buka file.
            FILE *file = fopen(filePath.c_str(), "rb");
            if (!file) {
                std::cerr << "Gagal membuka file: " << filePath << std::endl;
                return;
            }
    
            // Dapatkan ukuran file.
            fseek(file, 0, SEEK_END);
            long fileSize = ftell(file);
            fseek(file, 0, SEEK_SET);
    
            // Atur ukuran file.
            curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
    
            // Atur 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 yang dikembalikan: " << httpCode << std::endl;
    
                if (httpCode == 200) {
                    std::cout << "Berhasil diunggah menggunakan library jaringan." << std::endl;
                }
            }
    
            // Tutup file.
            fclose(file);
    
            // Bersihkan.
            curl_easy_cleanup(curl);
        }
    
        curl_global_cleanup();
    }
    
    int main() {
        // Ganti <signedUrl> dengan URL otorisasi.
        std::string signedUrl = "<signedUrl>";
    
        // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara 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, "Kode status yang dikembalikan: " + responseCode);
    
                    if (responseCode == 200) {
                        Log.d(TAG, "Berhasil diunggah menggunakan library jaringan.");
                    }
    
                    return "Unggah selesai. 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 otorisasi.
            String signedUrl = "<signedUrl>";
            // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
            String filePath = "C:\\Users\\demo.txt";
            activity.uploadFile(signedUrl, filePath);
        }
    }
    

Skenario Umum

Gunakan URL yang ditandatangani yang berisi header permintaan spesifik dan metadata pengguna untuk mengunggah objek

  1. Hasilkan URL yang ditandatangani dengan header permintaan spesifik dan metadata pengguna untuk mengizinkan permintaan HTTP PUT.

    import argparse
    import requests
    import alibabacloud_oss_v2 as oss
    
    from datetime import datetime, timedelta
    
    # Buat parser parameter baris perintah dan jelaskan tujuan skrip. Contoh ini menjelaskan cara menghasilkan URL yang ditandatangani yang mengizinkan permintaan HTTP PUT.
    parser = argparse.ArgumentParser(description="contoh presign put object")
    
    # Tentukan parameter baris perintah, termasuk wilayah, nama bucket, endpoint, dan nama objek yang diperlukan.
    parser.add_argument('--region', help='Wilayah tempat bucket berada.', required=True)
    parser.add_argument('--bucket', help='Nama bucket.', required=True)
    parser.add_argument('--endpoint', help='Nama domain yang dapat digunakan layanan lain untuk mengakses OSS')
    parser.add_argument('--key', help='Nama objek.', required=True)
    
    def main():
        # Parsing parameter baris perintah untuk mendapatkan nilai yang ditentukan oleh pengguna.
        args = parser.parse_args()
    
        # Dapatkan kredensial akses dari variabel lingkungan untuk otentikasi.
        credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    
        # Gunakan konfigurasi default SDK untuk membuat objek konfigurasi dan tentukan penyedia kredensial.
        cfg = oss.config.load_default()
        cfg.credentials_provider = credentials_provider
    
        # Tentukan atribut wilayah objek konfigurasi berdasarkan parameter baris perintah yang ditentukan oleh pengguna.
        cfg.region = args.region
    
        # Jika endpoint kustom disediakan, modifikasi parameter endpoint dalam objek konfigurasi.
        if args.endpoint is not None:
            cfg.endpoint = args.endpoint
    
        # Gunakan konfigurasi di atas untuk menginisialisasi instance OSSClient dan izinkan instance tersebut berinteraksi dengan OSS.
        client = oss.Client(cfg)
    
        # Kirim permintaan untuk memulai permintaan PUT dan hasilkan URL yang ditandatangani untuk objek yang ditentukan.
        pre_result = client.presign(oss.PutObjectRequest(
            bucket=args.bucket, # Nama bucket.
            key=args.key, # Nama objek.
            content_type='text/plain;charset=utf8', # Tentukan tipe objek.
            storage_class='Standard', # Tentukan kelas penyimpanan objek.
            metadata={
                'key1': 'value1', # Tentukan metadata objek.
                'key2': 'value2' # Tentukan metadata objek.
            }
        ),expires=timedelta(seconds=3600)) # Tentukan periode validitas permintaan. Dalam contoh ini, periode validitas diatur menjadi 3.600 detik.
    
    
        # Tampilkan metode, waktu kedaluwarsa, dan URL yang ditandatangani yang ditentukan dalam permintaan untuk memeriksa validitas URL yang ditandatangani.
        print(f'metode: {pre_result.method},'
              f' kedaluwarsa: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},'
              f' url: {pre_result.url}'
              )
    
        # Tampilkan header yang ditandatangani dalam permintaan, yang disertakan dalam header HTTP saat permintaan dikirim.
        for key, value in pre_result.signed_headers.items():
            print(f'header yang ditandatangani kunci: {key}, header yang ditandatangani nilai: {value}')
    
    # Panggil fungsi utama untuk memulai logika pemrosesan saat skrip dijalankan langsung.
    if __name__ == "__main__":
        main() # Tentukan titik masuk dalam fungsi skrip. Alur program kontrol dimulai di sini.
  2. Gunakan URL yang ditandatangani 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 otorisasi.
            URL signedUrl = new URL("<signedUrl>");
    
            // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
            String pathName = "C:\\Users\\demo.txt";
    
            // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan.
            Map<String, String> headers = new HashMap<String, String>();
            //Tentukan kelas penyimpanan objek.
            headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
            //Tentukan ContentType.
            headers.put(OSSHeaders.CONTENT_TYPE, "text/plain;charset=utf8");
    
            // Atur metadata kustom. Metadata kustom harus sama dengan metadata kustom yang digunakan saat URL dihasilkan.
            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 parameter header seperti metadata kustom dan kelas penyimpanan diatur saat URL yang ditandatangani dihasilkan, parameter ini juga harus dikirim ke server saat Anda menggunakan URL yang ditandatangani untuk mengunggah file. Jika tanda tangan yang dikirim ke server berbeda dari tanda tangan yang dihasilkan, 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 Anda menggunakan userMeta, SDK secara internal menambahkan awalan "x-oss-meta-" ke userMeta. Saat Anda menggunakan metode lain untuk menghasilkan URL yang ditandatangani untuk unggahan, Anda juga harus menambahkan awalan "x-oss-meta-" ke userMeta.
                    put.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString());
                }
    
                httpClient = HttpClients.createDefault();
    
                response = httpClient.execute(put);
    
                System.out.println("Kode status yang dikembalikan:"+response.getStatusLine().getStatusCode());
                if(response.getStatusLine().getStatusCode() == 200){
                    System.out.println("Berhasil diunggah menggunakan library jaringan.");
                }
                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.
    	file, err := os.Open(filePath)
    	if err != nil {
    		return err
    	}
    	defer file.Close()
    
    	// Baca isi file.
    	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
    	}
    
    	// Atur header permintaan.
    	for key, value := range headers {
    		req.Header.Set(key, value)
    	}
    
    	// Atur metadata kustom.
    	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 yang dikembalikan: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Berhasil diunggah menggunakan library jaringan.")
    	} else {
    		fmt.Println("Unggah gagal.")
    	}
    	body, _ := ioutil.ReadAll(resp.Body)
    	fmt.Println(string(body))
    
    	return nil
    }
    
    func main() {
    	// Ganti <signedUrl> dengan URL otorisasi.
    	signedUrl := "<signedUrl>"
    
    	// Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
    	filePath := "C:\\Users\\demo.txt"
    
    	// Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan.
    	headers := map[string]string{
    		"Content-Type": "text/plain;charset=utf8",
    		"x-oss-storage-class": "Standard",
    	}
    
    	// Atur metadata kustom. Metadata kustom harus sama dengan metadata kustom yang digunakan saat URL dihasilkan.
    	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 ditandatangani untuk mengunggah file ke OSS.
    
        :param signed_url: URL yang ditandatangani.
        :param file_path: Jalur lengkap file yang akan diunggah.
        :param headers: Opsional. Header HTTP kustom.
        :param metadata: Opsional. Metadata kustom.
        :return: None
        """
        if not headers:
            headers = {}
        if not metadata:
            metadata = {}
    
        # Perbarui header dan tambahkan awalan 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 yang dikembalikan: {response.status_code}")
                if response.status_code == 200:
                    print("Berhasil diunggah menggunakan library jaringan.")
                else:
                    print("Unggah gagal.")
                print(response.text)
        except Exception as e:
            print(f"Terjadi kesalahan: {e}")
    
    if __name__ == "__main__":
        # Ganti <signedUrl> dengan URL otorisasi.
        signed_url = "<signedUrl>"
       
        # Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari direktori tempat skrip berada secara default.
        file_path = "C:\\Users\\demo.txt"
    
        # Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan.
        headers = {
             "Content-Type": "text/plain;charset=utf8",
             "x-oss-storage-class": "Standard"
        }
    
        # Atur metadata kustom. Metadata kustom harus sama dengan metadata kustom yang digunakan saat URL dihasilkan.
        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 {
            // Perbarui header dan tambahkan awalan metadata.
            for (const [key, value] of Object.entries(metadata)) {
                headers[`x-oss-meta-${key}`] = value;
            }
    
            // Baca aliran file.
            const fileStream = fs.createReadStream(filePath);
    
            // Kirim permintaan PUT.
            const response = await axios.put(signedUrl, fileStream, {
                headers: headers
            });
    
            console.log(`Kode status yang dikembalikan: ${response.status}`);
            if (response.status === 200) {
                console.log("Berhasil diunggah menggunakan library jaringan.");
            } else {
                console.log("Unggah gagal.");
            }
            console.log(response.data);
        } catch (error) {
            console.error(`Terjadi kesalahan: ${error.message}`);
        }
    }
    
    // Fungsi utama.
    (async () => {
        // Ganti <signedUrl> dengan URL otorisasi.
        const signedUrl = "<signedUrl>";
    
        // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari direktori tempat skrip berada secara default.
        const filePath = "C:\\Users\\demo.txt";
    
        // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan.
        const headers = {
             "Content-Type": "text/plain;charset=utf8",
             "x-oss-storage-class": "Standard"
        };
    
        // Atur metadata kustom. Metadata kustom harus sama dengan metadata kustom yang digunakan saat URL dihasilkan.
        const metadata = {
             "key1": "value1",
             "key2": "value2"
        };
    
        await uploadFile(signedUrl, filePath, headers, metadata);
    })();
    

    Browser.js

    Penting

    Jika Anda menggunakan Browser.js untuk mengunggah file dan mengalami kesalahan 403 SignatureDoesNotMatch, kesalahan ini biasanya terjadi karena browser secara otomatis menambahkan header permintaan Content-Type. Jika header ini tidak ditentukan saat URL yang ditandatangani dihasilkan, verifikasi tanda tangan gagal. Untuk menyelesaikan masalah ini, Anda harus menentukan header permintaan Content-Type saat menghasilkan URL yang ditandatangani.

    <!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 (OSS SDK untuk Java)</h1>
    
        <input type="file" id="fileInput" />
        <button id="uploadButton">Unggah File</button>
    
        <script>
            // Ganti ini dengan URL yang 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 saat 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. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
    var filePath = "C:\\Users\\demo.txt";
    // Ganti <signedUrl> dengan URL otorisasi.
    var presignedUrl = "<signedUrl>";
    
    // Buat klien HTTP dan buka 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 parameter header seperti metadata kustom dan kelas penyimpanan diatur saat URL yang ditandatangani dihasilkan, parameter ini juga harus dikirim ke server saat Anda menggunakan URL yang ditandatangani untuk mengunggah file. Jika tanda tangan yang dikirim ke server berbeda dari tanda tangan yang dihasilkan, kesalahan tanda tangan dilaporkan.
    // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan.
    request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain") { CharSet = "utf8" };  // Tentukan ContentType.       
    // Atur metadata kustom. Metadata kustom harus sama dengan metadata kustom yang digunakan saat URL dihasilkan.
    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($"Berhasil 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>
    
    // Fungsi callback yang digunakan untuk memproses tanggapan 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) {
            // Atur URL.
            curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str());
    
            // Atur metode permintaan ke PUT.
            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    
            // Buka file.
            FILE* file = fopen(filePath.c_str(), "rb");
            if (!file) {
                std::cerr << "Gagal membuka file: " << filePath << std::endl;
                return;
            }
    
            // Atur ukuran file.
            fseek(file, 0, SEEK_END);
            long fileSize = ftell(file);
            rewind(file);
    
            // Atur callback pembacaan file.
            curl_easy_setopt(curl, CURLOPT_READDATA, file);
            curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
    
            // Atur 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);
    
            // Atur callback pemrosesan tanggapan.
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
    
            // Eksekusi permintaan.
            res = curl_easy_perform(curl);
    
            // Periksa tanggapan.
            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 yang dikembalikan: " << responseCode << std::endl;
                if (responseCode == 200) {
                    std::cout << "Berhasil diunggah menggunakan library jaringan." << std::endl;
                } else {
                    std::cout << "Unggah gagal." << std::endl;
                }
                std::cout << readBuffer << std::endl;
            }
    
            // Bersihkan.
            fclose(file);
            curl_slist_free_all(chunk);
            curl_easy_cleanup(curl);
        }
    
        curl_global_cleanup();
    }
    
    int main() {
        // Ganti <signedUrl> dengan URL otorisasi.
        std::string signedUrl = "<signedUrl>";
    
        // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
        std::string filePath = "C:\\Users\\demo.txt";
    
        // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan.
        std::map<std::string, std::string> headers = {
             {"Content-Type", "text/plain;charset=utf8"},
             {"x-oss-storage-class", "Standard"}
        };
    
        // Atur metadata kustom. Metadata kustom harus sama dengan metadata kustom yang digunakan saat URL dihasilkan.
        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 otorisasi.
            String signedUrl = "<signedUrl>";
    
            // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
            String pathName = "/storage/emulated/0/demo.txt";
    
            // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan.
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "text/plain;charset=utf8");
            headers.put("x-oss-storage-class", "Standard");
    
            // Atur metadata kustom. Metadata kustom harus sama dengan metadata kustom yang digunakan saat URL dihasilkan.
            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);
    
                    // Atur header permintaan.
                    for (Entry<String, String> header : headers.entrySet()) {
                        connection.setRequestProperty(header.getKey(), header.getValue());
                    }
    
                    // Atur metadata kustom.
                    for (Entry<String, String> meta : userMetadata.entrySet()) {
                        connection.setRequestProperty("x-oss-meta-" + meta.getKey(), meta.getValue());
                    }
    
                    // Baca 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();
    
                    // Dapatkan tanggapan.
                    int responseCode = connection.getResponseCode();
                    Log.d(TAG, "Kode status yang dikembalikan: " + responseCode);
                    if (responseCode == 200) {
                        Log.d(TAG, "Berhasil diunggah menggunakan library jaringan.");
                    } 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, "Berhasil diunggah.", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SignUrlUploadActivity.this, "Unggah gagal.", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
    

Gunakan URL yang ditandatangani untuk mengunggah objek menggunakan unggahan multipart

Untuk menggunakan URL yang ditandatangani untuk mengunggah objek menggunakan unggahan multipart, Anda harus mengonfigurasi ukuran bagian dan menghasilkan URL yang ditandatangani untuk setiap bagian. Contoh kode:

import argparse
import os
import requests
import alibabacloud_oss_v2 as oss

# Buat parser parameter baris perintah dan jelaskan tujuan skrip. Contoh ini menjelaskan cara menghasilkan URL yang ditandatangani untuk mengunggah objek menggunakan unggahan multipart.
parser = argparse.ArgumentParser(description="contoh presign multipart upload")

# Tentukan parameter --region, yang menentukan wilayah tempat bucket berada. Parameter baris perintah ini diperlukan.
parser.add_argument('--region', help='Wilayah tempat bucket berada.', required=True)
# Tentukan parameter --bucket, yang menentukan wilayah tempat bucket berada. Parameter baris perintah ini diperlukan.
parser.add_argument('--bucket', help='Nama bucket.', required=True)
# Tentukan parameter --endpoint, yang menentukan titik akhir yang dapat digunakan layanan lain untuk mengakses OSS. Parameter baris perintah ini opsional.
parser.add_argument('--endpoint', help='Nama domain yang dapat digunakan layanan lain untuk mengakses OSS')
# Tentukan parameter --key, yang menentukan nama objek. Parameter baris perintah ini diperlukan.
parser.add_argument('--key', help='Nama objek.', required=True)
# Tentukan parameter --file_path, yang menentukan jalur tempat Anda ingin menyimpan objek. Parameter baris perintah ini diperlukan.
parser.add_argument('--file_path', help='Jalur file unggahan.', required=True)

def main():
    # Parsing parameter baris perintah untuk mendapatkan nilai yang dimasukkan oleh pengguna.
    args = parser.parse_args()

    # Muat informasi autentikasi yang diperlukan untuk mengakses OSS dari variabel lingkungan.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Gunakan konfigurasi default SDK untuk membuat objek cfg dan tentukan penyedia kredensial.
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # Tentukan atribut wilayah objek cfg berdasarkan parameter baris perintah yang ditentukan oleh pengguna.
    cfg.region = args.region

    # Jika endpoint kustom disediakan, modifikasi atribut endpoint objek cfg dengan endpoint yang disediakan.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Gunakan konfigurasi di atas untuk menginisialisasi instance OSSClient dan izinkan instance tersebut berinteraksi dengan OSS.
    client = oss.Client(cfg)

    // Set ukuran bagian menjadi 1 MB.
    part_size = 1024 * 1024
    // Dapatkan ukuran file lokal.
    data_size = os.path.getsize(args.file_path)
    part_number = 1
    upload_parts = []

    // Mulai permintaan unggahan multipart.
    init_pre_result = client.presign(oss.InitiateMultipartUploadRequest(
        bucket=args.bucket,
        key=args.key,
    ))

    // Kirim permintaan unggahan multipart.
    with requests.post(init_pre_result.url, headers=init_pre_result.signed_headers) as resp:
        obj = oss.InitiateMultipartUploadResult()
        oss.serde.deserialize_xml(xml_data=resp.content, obj=obj)

        // Buka file lokal dan baca kontennya.
        with open(args.file_path, 'rb') as f:
            for start in range(0, data_size, part_size):
                n = part_size
                if start + n > data_size:
                    n = data_size - start
                reader = oss.io_utils.SectionReader(oss.io_utils.ReadAtReader(f), start, n)

                // Mulai permintaan untuk menghasilkan URL yang ditandatangani untuk sebuah bagian.
                up_pre_result = client.presign(oss.UploadPartRequest(
                    bucket=args.bucket,
                    key=args.key,
                    upload_id=obj.upload_id,
                    part_number=part_number,
                ))

                // Pisahkan file lokal menjadi bagian-bagian.
                with requests.put(up_pre_result.url, headers=up_pre_result.signed_headers, data=reader) as up_result:
                    print(f'kode status: {up_result.status_code},'
                          f' ID permintaan: {up_result.headers.get("x-oss-request-id")},'
                          f' nomor bagian: {part_number},'
                          f' hash crc64: {up_result.headers.get("x-oss-hash-crc64ecma")},'
                          f' content md5: {up_result.headers.get("Content-MD5")},'
                          f' etag: {up_result.headers.get("ETag")},'
                          f' waktu server: {up_result.headers.get("x-oss-server-time")}'
                    )

                    // Rekam ETag dan nomor setiap bagian.
                    upload_parts.append(oss.UploadPart(part_number=part_number, etag=up_result.headers.get("ETag")))
                part_number += 1

        // Urutkan bagian berdasarkan nomor bagian.
        parts = sorted(upload_parts, key=lambda p: p.part_number)

        // Selesaikan permintaan unggahan multipart.
        request = oss.CompleteMultipartUploadRequest(
            bucket=args.bucket,
            key=args.key,
            upload_id=obj.upload_id,
            complete_multipart_upload=oss.CompleteMultipartUpload(
                parts=parts
            )
        )

        // Serialisasi parameter.
        op_input = oss.serde.serialize_input(request, oss.OperationInput(
            op_name='CompleteMultipartUpload',
            method='POST',
            bucket=request.bucket,
        ))

        // Hasilkan permintaan untuk mengunggah file lokal menggunakan unggahan multipart.
        complete_pre_result = client.presign(request)

        //Selesaikan permintaan unggahan multipart.
        with requests.post(complete_pre_result.url, headers=complete_pre_result.signed_headers, data=op_input.body) as complete_resp:
            result = oss.CompleteMultipartUploadResult()
            oss.serde.deserialize_xml(xml_data=complete_resp.content, obj=result)
            print(f'kode status: {complete_resp.status_code},'
                  f' ID permintaan: {complete_resp.headers.get("x-oss-request-id")},'
                  f' hash crc64: {complete_resp.headers.get("x-oss-hash-crc64ecma")},'
                  f' content md5: {complete_resp.headers.get("Content-MD5")},'
                  f' etag: {complete_resp.headers.get("ETag")},'
                  f' panjang konten: {complete_resp.headers.get("content-length")},'
                  f' tipe konten: {complete_resp.headers.get("Content-Type")},'
                  f' url: {result.location},'
                  f' jenis pengkodean: {result.encoding_type},'
                  f' waktu server: {complete_resp.headers.get("x-oss-server-time")}'
            )

        // Tampilkan metode, waktu kedaluwarsa, dan URL yang ditandatangani yang dikembalikan untuk permintaan.
        print(f'metode: {complete_pre_result.method},'
              f' kedaluwarsa: {complete_pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},'
              f' url: {complete_pre_result.url}'
        )

        // Tampilkan header yang ditandatangani dalam permintaan.
        for key, value in complete_pre_result.signed_headers.items():
            print(f'header yang ditandatangani kunci: {key}, header yang ditandatangani nilai: {value}')

# Panggil fungsi utama untuk memulai logika pemrosesan saat skrip dijalankan langsung.
if __name__ == "__main__":
    main() # Tentukan titik masuk dalam fungsi skrip. Alur program kontrol dimulai di sini.

Gunakan URL yang ditandatangani untuk mengunggah objek dan atur parameter callback unggah

  1. Hasilkan URL yang ditandatangani dengan parameter callback unggah untuk mengaktifkan unggahan menggunakan permintaan HTTP PUT.

    import argparse
    import base64
    import requests
    import alibabacloud_oss_v2 as oss
    
    from datetime import datetime, timedelta
    
    # Buat parser parameter baris perintah dan jelaskan tujuan skrip. Contoh ini menjelaskan cara menghasilkan URL yang ditandatangani yang mengizinkan permintaan HTTP PUT.
    parser = argparse.ArgumentParser(description="contoh presign put object")
    
    # Tentukan parameter baris perintah, termasuk wilayah, nama bucket, endpoint, dan nama objek yang diperlukan.
    parser.add_argument('--region', help='Wilayah tempat bucket berada.', required=True)
    parser.add_argument('--bucket', help='Nama bucket.', required=True)
    parser.add_argument('--endpoint', help='Nama domain yang dapat digunakan layanan lain untuk mengakses OSS')
    parser.add_argument('--key', help='Nama objek.', required=True)
    
    def main():
        # Parsing parameter baris perintah.
        args = parser.parse_args()
    
        # Dapatkan kredensial akses dari variabel lingkungan untuk otentikasi.
        credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    
        // Gunakan konfigurasi default untuk membuat objek cfg dan tentukan penyedia kredensial.
        cfg = oss.config.load_default()
        cfg.credentials_provider = credentials_provider
    
        // Atur atribut wilayah objek cfg ke wilayah yang disediakan dalam parameter baris perintah.
        cfg.region = args.region
    
        // Jika endpoint kustom disediakan, perbarui atribut endpoint objek cfg dengan endpoint yang disediakan.
        if args.endpoint is not None:
            cfg.endpoint = args.endpoint
    
        // Gunakan konfigurasi di atas untuk menginisialisasi instance OSSClient.
        client = oss.Client(cfg)
    
        // Tentukan URL callback kustom.
        call_back_url = "http://www.example.com/callback"
        // Konstruksi parameter callback: tentukan URL callback dan badan permintaan, dan enkode parameter dalam Base64.
        callback=base64.b64encode(str('{\"callbackUrl\":\"' + call_back_url + '\",\"callbackBody\":\"bucket=${bucket}&object=${object}&my_var_1=${x:var1}&my_var_2=${x:var2}\"}').encode()).decode()
        // Definisikan dan enkode variabel callback kustom dalam Base64.
        callback_var=base64.b64encode('{\"x:var1\":\"value1\",\"x:var2\":\"value2\"}'.encode()).decode()
    
        // Kirim permintaan untuk memulai permintaan PUT dan hasilkan URL yang ditandatangani untuk objek yang ditentukan.
        pre_result = client.presign(oss.PutObjectRequest(
            bucket=args.bucket,  # Nama bucket.
            key=args.key,  # Nama objek.
            callback=callback,
            callback_var=callback_var,
        ),expires=timedelta(seconds=3600)) # Tentukan periode validitas permintaan. Dalam contoh ini, periode validitas diatur menjadi 3.600 detik.
    
        // Tampilkan metode, waktu kedaluwarsa, dan URL yang ditandatangani yang ditentukan dalam permintaan untuk memeriksa validitas URL yang ditandatangani.
        print(f'metode: {pre_result.method},'
              f' kedaluwarsa: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},'
              f' url: {pre_result.url}'
              )
    
        // Tampilkan header yang ditandatangani dalam permintaan, yang disertakan dalam header HTTP saat permintaan dikirim.
        for key, value in pre_result.signed_headers.items():
            print(f'header yang ditandatangani kunci: {key}, header yang ditandatangani nilai: {value}')
    
    // Panggil fungsi utama untuk memulai logika pemrosesan saat skrip dijalankan langsung.
    if __name__ == "__main__":
        main()  # Tentukan titik masuk skrip. Alur kontrol dimulai di sini.
  2. Gunakan URL yang ditandatangani untuk mengunggah objek.

    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):
        """
        Gunakan URL yang ditandatangani untuk mengunggah objek ke OSS.
    
        :param signed_url: URL yang ditandatangani.
        :param file_path: Jalur lengkap file lokal yang akan diunggah.
        :param headers: Header permintaan. Parameter ini opsional.
        :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"Kode status: {response.status_code}")
                if response.status_code == 200:
                    print("Objek diunggah menggunakan library.")
                else:
                    print("Unggah gagal.")
                print(response.text)
        except Exception as e:
            print(f"Terjadi kesalahan: {e}")
    
    if __name__ == "__main__":
        // Ganti <signedUrl> dengan URL yang ditandatangani.
        signed_url = "<signedUrl>"
    
        // Tentukan jalur lengkap file lokal. Secara default, jika Anda tidak menentukan jalur lengkap file lokal, file lokal diunggah dari direktori tempat skrip disimpan.
        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 {
    	// Buka file.
    	file, err := os.Open(filePath)
    	if err != nil {
    		return err
    	}
    	defer file.Close()
    
    	// Baca konten.
    	fileBytes, err := io.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.Add(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 library.")
    	} else {
    		fmt.Println("Unggah gagal.")
    	}
    	body, _ := io.ReadAll(resp.Body)
    	fmt.Println(string(body))
    
    	return nil
    }
    
    func main() {
    	// Ganti <signedUrl> dengan URL yang ditandatangani.
    	signedUrl := "<signedUrl>"
    	// Tentukan jalur lengkap file lokal. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada.
    	filePath := "C:\\Users\\demo.txt"
    
    	// Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang ditandatangani dihasilkan.
    	headers := map[string]string{
    		"x-oss-callback":     "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9",
    		"x-oss-callback-var": "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==",
    	}
    
    	err := uploadFile(signedUrl, filePath, headers)
    	if err != nil {
    		fmt.Printf("Terjadi kesalahan: %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 Throwable {
            CloseableHttpClient httpClient = null;
            CloseableHttpResponse response = null;
    
            // Ganti <signedUrl> dengan URL yang ditandatangani.
            URL signedUrl = new URL("<signedUrl>");
    
            // Tentukan jalur lengkap file lokal. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada.
            String pathName = "C:\\Users\\demo.txt";
    
            // Tentukan header permintaan, termasuk x-oss-callback dan 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);
                // Jika Anda mengonfigurasi header saat URL yang ditandatangani dihasilkan, header ini harus dikirim ke server saat URL yang ditandatangani digunakan untuk mengunggah file. Jika header yang dikirim ke server untuk perhitungan tanda tangan berbeda dari header yang ditentukan saat URL yang ditandatangani dihasilkan, kesalahan tanda tangan dilaporkan.
                for(Map.Entry header: headers.entrySet()){
                    put.addHeader(header.getKey().toString(),header.getValue().toString());
                }
    
                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 library.");
                }
                System.out.println(response.toString());
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                response.close();
                httpClient.close();
            }
        }
    }       

    PHP

    <?php
    
    function uploadFile($signedUrl, $filePath, $headers = []) {
        // Periksa apakah file ada.
        if (!file_exists($filePath)) {
            echo "File tidak ada: $filePath\n";
            return;
        }
    
        // Inisialisasi sesi cURL.
        $ch = curl_init();
    
        // Atur opsi cURL.
        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));
    
        // Lakukan permintaan cURL.
        $response = curl_exec($ch);
    
        // Query kode status HTTP.
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
        // Tutup sesi cURL.
        curl_close($ch);
    
        // Keluarkan hasil
        echo "Kode status: $httpCode\n";
        if ($httpCode == 200) {
            echo "Objek diunggah menggunakan library.\n";
        } else {
            echo "Unggah gagal.\n";
        }
        echo $response . "\n";
    }
    
    // Ganti <signedUrl> dengan URL yang ditandatangani.
    $signedUrl = "<signedUrl>";
    
    // Tentukan jalur lengkap file lokal. Secara default, jika Anda tidak menentukan jalur lengkap file lokal, file lokal diunggah dari direktori tempat skrip disimpan.
    $filePath = "C:\\Users\\demo.txt";
    
    $headers = [
        "x-oss-callback" => "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9",
        "x-oss-callback-var" => "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==",
    ];
    
    uploadFile($signedUrl, $filePath, $headers);
    
    ?>

Tanya Jawab Umum

Ketika saya menggunakan URL yang ditandatangani untuk mengunggah file lokal, apakah file tersebut terunggah jika URL yang ditandatangani kedaluwarsa selama proses unggah?

Ya, file tetap terunggah meskipun URL yang ditandatangani kedaluwarsa selama proses unggah.

URL yang ditandatangani digunakan selama proses unggah. URL tersebut dapat digunakan dalam jangka waktu validitasnya. Jangka waktu validitas URL adalah nilai minimum dari jangka waktu validitas token dan jangka waktu validitas yang telah ditentukan sebelumnya.

Jika saya tidak menentukan header permintaan dan metadata pengguna saat menghasilkan URL, apakah saya perlu menentukan header permintaan dan metadata pengguna saat menggunakan URL untuk mengunggah file lokal?

Anda tidak perlu menentukan header permintaan dan metadata pengguna.

Header permintaan dan metadata pengguna adalah parameter opsional. Jika Anda tidak menentukan header permintaan dan metadata pengguna, hapus kode terkait dalam contoh di atas.

Referensi