All Products
Search
Document Center

Object Storage Service:Gunakan URL yang ditandatangani sebelumnya untuk mengunggah file

Last Updated:Aug 28, 2026

Secara default, daftar kontrol akses (ACL) objek dalam bucket Object Storage Service (OSS) bersifat privat, dan hanya pemilik objek yang memiliki izin untuk mengakses objek tersebut. Anda dapat menggunakan OSS SDK untuk Go guna menghasilkan URL yang ditandatangani sebelumnya, lalu membagikannya kepada pengguna agar mereka dapat mengunggah objek. Saat menghasilkan URL yang ditandatangani sebelumnya, Anda dapat menentukan periode validitasnya untuk membatasi waktu pengguna dalam mengunggah objek. Selama periode validitas tersebut, pengguna dapat menggunakan URL itu untuk mengunggah objek ke bucket beberapa kali. Setelah periode validitas berakhir, pengguna tidak lagi dapat menggunakan URL tersebut untuk mengunggah objek. Untuk memperpanjang akses bagi pengguna, hasilkan kembali URL yang ditandatangani sebelumnya.

Catatan penggunaan

  • Topik ini menggunakan titik akhir publik wilayah China (Hangzhou). Untuk mengakses OSS dari layanan Alibaba Cloud lainnya di wilayah yang sama, gunakan titik akhir internal. Untuk detail wilayah dan titik akhir yang didukung, lihat Wilayah dan titik akhir.

  • Topik ini memperoleh kredensial akses dari variabel lingkungan. Untuk informasi lebih lanjut tentang cara mengonfigurasi kredensial akses, lihat Konfigurasikan kredensial akses (Go SDK V1).

  • Topik ini menunjukkan pembuatan instans OSSClient dengan titik akhir OSS. Untuk konfigurasi alternatif, seperti menggunakan domain kustom atau autentikasi dengan kredensial dari Security Token Service (STS), lihat Konfigurasi client.

  • Izin tidak diperlukan untuk menghasilkan URL yang ditandatangani sebelumnya. Namun, pihak ketiga hanya dapat berhasil mengunggah file menggunakan URL tersebut jika Anda memiliki izin oss:PutObject. Untuk informasi lebih lanjut, lihat Berikan kebijakan akses kustom kepada RAM user.

  • Topik ini menggunakan algoritma tanda tangan V4 untuk menghasilkan URL yang ditandatangani sebelumnya dengan periode validitas hingga 7 hari. Untuk informasi lebih lanjut, lihat (Disarankan) Tanda tangan V4 dalam URL yang ditandatangani sebelumnya.

Proses

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

Gunakan URL yang ditandatangani sebelumnya untuk unggah simple

  1. Pemilik objek menghasilkan URL yang ditandatangani sebelumnya yang mengizinkan permintaan HTTP PUT.

    package main
    
    import (
    	"log"
    
    	"github.com/aliyun/aliyun-oss-go-sdk/oss"
    )
    
    func main() {
    	// Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
    	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    
    	// Buat instans OSSClient.
    	// Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com.
    	// Tentukan wilayah bucket. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou.
    	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
    	clientOptions = append(clientOptions, oss.Region("cn-hangzhou"))
    	// Tentukan versi algoritma tanda tangan.
    	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
    	client, err := oss.New("https://oss-cn-hangzhou.aliyuncs.com", "", "", clientOptions...)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    
    	// Tentukan nama bucket. Contoh: examplebucket.
    	bucketName := "examplebucket"
    	// Tentukan path lengkap objek. Contoh: exampleobject.txt. Jangan sertakan nama bucket dalam path lengkap.
    	objectName := "exampleobject.txt"
    	bucket, err := client.Bucket(bucketName)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    
    	// Hasilkan URL yang ditandatangani sebelumnya dan atur periode validitasnya menjadi 600 detik.
    	signedURL, err := bucket.SignURL(objectName, oss.HTTPPut, 600)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    	log.Printf("Sign Url:%s\n", signedURL)
    }
  2. Pengguna menggunakan URL yang ditandatangani sebelumnya untuk mengunggah file lokal.

    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 yang diotorisasi.
            URL signedUrl = new URL("<signedUrl>");
    
            // Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh 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 untuk unggahan:"+response.getStatusLine().getStatusCode());
                if(response.getStatusLine().getStatusCode() == 200){
                    System.out.println("Unggah berhasil menggunakan library jaringan.");
                }
                System.out.println(response.toString());
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                 if (response != null) {
                     response.close();
                 }
                 if (httpClient != null) {
                     httpClient.close();
                 }
             }
        }
    }       

    Go

    package main
    
    import (
    	"fmt"
    	"io"
    	"net/http"
    	"os"
    )
    
    func uploadFile(signedUrl, filePath string) error {
    	// Buka file.
    	file, err := os.Open(filePath)
    	if err != nil {
    		return fmt.Errorf("Tidak dapat membuka file: %w", err)
    	}
    	defer file.Close()
    
    	// Buat client 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 respons.
    	body, err := io.ReadAll(resp.Body)
    	if err != nil {
    		return fmt.Errorf("Gagal membaca respons: %w", err)
    	}
    
    	fmt.Printf("Kode status yang dikembalikan untuk unggahan: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Unggah berhasil menggunakan library jaringan.")
    	}
    	fmt.Println(string(body))
    
    	return nil
    }
    
    func main() {
    	// Ganti <signedUrl> dengan URL yang diotorisasi.
    	signedUrl := "<signedUrl>"
    
    	// Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh 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 untuk unggahan: {response.status_code}")
            if response.status_code == 200:
                print("Unggah berhasil menggunakan library jaringan.")
            print(response.text)
     
        except Exception as e:
            print(f"Terjadi kesalahan: {e}")
    
    if __name__ == "__main__":
        # Ganti <signedUrl> dengan URL yang diotorisasi.
        signed_url = "<signedUrl>"
        
        # Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh secara default.
        file_path = "C:\\Users\\demo.txt"
    
        upload_file(signed_url, file_path)
    

    Node.js

    Penting

    Jika Anda mengalami error ketidakcocokan signature 403 saat menggunakan Node.js untuk mengunggah file, biasanya karena header permintaan Content-Type secara eksplisit diatur dalam permintaan unggah, tetapi header ini tidak disertakan saat URL yang ditandatangani sebelumnya dihasilkan. Ketidakcocokan ini menyebabkan kegagalan verifikasi signature. Untuk mengatasi masalah ini, jangan atur header permintaan Content-Type dalam permintaan unggah, atau tentukan header permintaan Content-Type saat menghasilkan URL yang ditandatangani sebelumnya.

    const fs = require('fs');
    const axios = require('axios');
    
    async function uploadFile(signedUrl, filePath) {
        try {
            // Buat stream baca.
            const fileStream = fs.createReadStream(filePath);
    
            // Kirim permintaan PUT untuk mengunggah file.
            const response = await axios.put(signedUrl, fileStream);
    
            console.log(`Kode status yang dikembalikan untuk unggahan: ${response.status}`);
            if (response.status === 200) {
                console.log('Unggah berhasil menggunakan library jaringan.');
            }
            console.log(response.data);
        } catch (error) {
            console.error(`Terjadi kesalahan: ${error.message}`);
        }
    }
    
    // Fungsi utama.
    (async () => {
        // Ganti <signedUrl> dengan URL yang diotorisasi.
        const signedUrl = '<signedUrl>';
        
        // Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh secara default.
        const filePath = 'C:\\Users\\demo.txt';
    
        await uploadFile(signedUrl, filePath);
    })();

    browser.js

    Penting

    Jika Anda mengalami error ketidakcocokan signature 403 saat menggunakan Browser.js untuk mengunggah file, biasanya karena browser secara otomatis menambahkan header permintaan Content-Type, dan header ini tidak disertakan saat URL yang ditandatangani sebelumnya dihasilkan. Ketidakcocokan ini menyebabkan kegagalan verifikasi signature. Untuk mengatasi masalah ini, Anda harus menentukan header permintaan Content-Type saat menghasilkan URL yang ditandatangani sebelumnya.

    <!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 sebelumnya 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 unggah:', error);
                    alert('Unggah gagal: ' + error.message);
                }
            });
    
            /**
             * Unggah file ke OSS.
             * @param {File} file - File yang akan diunggah.
             * @param {string} presignedUrl - URL yang ditandatangani sebelumnya.
             */
            const upload = async (file, presignedUrl) => {
                const response = await fetch(presignedUrl, {
                    method: 'PUT',
                    body: file,  // Unggah seluruh file secara langsung.
                });
    
                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 path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh secara default.
    var filePath = "C:\\Users\\demo.txt";
    // Ganti <signedUrl> dengan URL yang diotorisasi.
    var presignedUrl = "<signedUrl>";
    
    // Buat client HTTP dan buka stream 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 respons.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Unggah berhasil! Kode status: {response.StatusCode}");
        Console.WriteLine("Header respons:");
        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 respons: " + 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 menjadi PUT.
            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    
            // Buka file.
            FILE *file = fopen(filePath.c_str(), "rb");
            if (!file) {
                std::cerr << "Tidak dapat 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);
    
            // Jalankan 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 untuk unggahan: " << httpCode << std::endl;
    
                if (httpCode == 200) {
                    std::cout << "Unggah berhasil menggunakan library jaringan." << std::endl;
                }
            }
    
            // Tutup file.
            fclose(file);
    
            // Bersihkan.
            curl_easy_cleanup(curl);
        }
    
        curl_global_cleanup();
    }
    
    int main() {
        // Ganti <signedUrl> dengan URL yang diotorisasi.
        std::string signedUrl = "<signedUrl>";
    
        // Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh 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 untuk unggahan: " + responseCode);
    
                    if (responseCode == 200) {
                        Log.d(TAG, "Unggah berhasil 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 yang diotorisasi.
            String signedUrl = "<signedUrl>";
            // Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh secara default.
            String filePath = "C:\\Users\\demo.txt";
            activity.uploadFile(signedUrl, filePath);
        }
    }
    

Skenario umum

Gunakan URL yang ditandatangani sebelumnya yang berisi header permintaan dan metadata pengguna tertentu untuk mengunggah file

  1. Pemilik objek menghasilkan URL yang ditandatangani sebelumnya yang berisi header permintaan dan metadata pengguna tertentu serta mengizinkan permintaan HTTP PUT.

    package main
    
    import (
    	"log"
    
    	"github.com/aliyun/aliyun-oss-go-sdk/oss"
    )
    
    func main() {
    	// Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
    	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    
    	// Buat instans OSSClient.
    	// Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com.
    	// Tentukan wilayah bucket. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou.
    	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
    	clientOptions = append(clientOptions, oss.Region("cn-hangzhou"))
    	// Tentukan versi algoritma tanda tangan.
    	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
    	client, err := oss.New("https://oss-cn-hangzhou.aliyuncs.com", "", "", clientOptions...)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    
    	// Tentukan nama bucket. Contoh: examplebucket.
    	bucketName := "examplebucket"
    	// Tentukan path lengkap objek. Contoh: exampleobject.txt. Jangan sertakan nama bucket dalam path lengkap.
    	objectName := "exampleobject.txt"
    	bucket, err := client.Bucket(bucketName)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    	// Perhatikan bahwa saat Anda menggunakan URL yang ditandatangani sebelumnya yang berisi parameter kustom di antarmuka depan, Anda harus menentukan tipe konten yang sama seperti yang ditentukan di sini saat menghasilkan URL yang ditandatangani sebelumnya.
    	options := []oss.Option{
    		oss.Meta("key1", "value1"),
    		oss.Meta("key2", "value2"),
    		oss.ContentType("text/plain; charset=utf8"),
    	}
    
    	// Hasilkan URL yang ditandatangani sebelumnya dan atur periode validitasnya menjadi 600 detik.
    	signedURL, err := bucket.SignURL(objectName, oss.HTTPPut, 600, options...)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    	log.Printf("Sign Url:%s\n", signedURL)
    }
    
  2. Pengguna menggunakan URL yang ditandatangani sebelumnya untuk mengunggah file lokal.

    curl

    curl -X PUT \
         -H "Content-Type: text/plain;charset=utf8" \
         -H "x-oss-storage-class: Standard" \
         -H "x-oss-meta-key1: value1" \
         -H "x-oss-meta-key2: value2" \
         -T "C:\\Users\\demo.txt" \
         "https://exampleobject.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T083238Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"

    Java

    package com.aliyun.sample;
    
    import com.aliyun.oss.internal.OSSHeaders;
    import com.aliyun.oss.model.StorageClass;
    import org.apache.http.HttpEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPut;
    import org.apache.http.entity.FileEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import java.io.*;
    import java.net.URL;
    import java.util.*;
    
    public class SignUrlUpload {
        public static void main(String[] args) throws Throwable {
            CloseableHttpClient httpClient = null;
            CloseableHttpResponse response = null;
    
            // Ganti <signedUrl> dengan URL yang diotorisasi.
            URL signedUrl = new URL("<signedUrl>");
    
            // Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh 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 pengguna kustom. Metadata pengguna kustom harus sama dengan informasi 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 Anda mengatur parameter header, seperti metadata pengguna dan kelas penyimpanan, saat menghasilkan URL yang ditandatangani sebelumnya, Anda juga harus mengirim parameter ini ke server saat menggunakan URL tersebut untuk mengunggah file. Error signature akan dilaporkan jika parameter yang dikirim ke server tidak konsisten dengan parameter yang ditandatangani.
                for(Map.Entry<String, String> header: headers.entrySet()){
                    put.addHeader(header.getKey(), header.getValue());
                }
                for(Map.Entry<String, String> meta: userMetadata.entrySet()){
                    // Jika Anda menggunakan userMeta, SDK secara internal menambahkan awalan 'x-oss-meta-'. Saat Anda menggunakan metode lain untuk menghasilkan URL yang ditandatangani sebelumnya untuk unggah, Anda juga harus menambahkan awalan 'x-oss-meta-' ke userMeta.
                    put.addHeader("x-oss-meta-"+meta.getKey(), meta.getValue());
                }
    
                httpClient = HttpClients.createDefault();
    
                response = httpClient.execute(put);
    
                System.out.println("Kode status yang dikembalikan untuk unggahan:"+response.getStatusLine().getStatusCode());
                if(response.getStatusLine().getStatusCode() == 200){
                    System.out.println("Unggah berhasil menggunakan library jaringan.");
                }
                System.out.println(response.toString());
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            }
        }
    }

    Go

    package main
    
    import (
    	"bytes"
    	"fmt"
    	"io/ioutil"
    	"net/http"
    	"os"
    )
    
    func uploadFile(signedUrl string, filePath string, headers map[string]string, metadata map[string]string) error {
    	// Buka file.
    	file, err := os.Open(filePath)
    	if err != nil {
    		return err
    	}
    	defer file.Close()
    
    	// Baca konten 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 pengguna 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 respons.
    	fmt.Printf("Kode status yang dikembalikan untuk unggahan: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Unggah berhasil 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 yang diotorisasi.
    	signedUrl := "<signedUrl>"
    
    	// Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh 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 pengguna kustom. Metadata pengguna kustom harus sama dengan informasi 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: Tidak ada
        """
        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"Status code returned for the upload: {response.status_code}")
                if response.status_code == 200:
                    print("Upload successful using network library.")
                else:
                    print("Upload failed.")
                print(response.text)
        except Exception as e:
            print(f"An error occurred: {e}")
    
    if __name__ == "__main__":
        # Ganti <signedUrl> dengan URL yang diotorisasi.
        signed_url = "<signedUrl>"
       
        # Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file akan 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 dibuat.
        headers = {
             "Content-Type": "text/plain;charset=utf8",
             "x-oss-storage-class": "Standard"
        }
    
        # Atur metadata pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL 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 {
            // Perbarui header dan tambahkan awalan metadata.
            for (const [key, value] of Object.entries(metadata)) {
                headers[`x-oss-meta-${key}`] = value;
            }
    
            // Baca stream file.
            const fileStream = fs.createReadStream(filePath);
    
            // Kirim permintaan PUT.
            const response = await axios.put(signedUrl, fileStream, {
                headers: headers
            });
    
            console.log(`Kode status yang dikembalikan untuk unggahan: ${response.status}`);
            if (response.status === 200) {
                console.log("Unggah berhasil 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 yang diotorisasi.
        const signedUrl = "<signedUrl>";
    
        // Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan 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 pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL dihasilkan.
        const metadata = {
             "key1": "value1",
             "key2": "value2"
        };
    
        await uploadFile(signedUrl, filePath, headers, metadata);
    })();
    

    Browser.js

    Penting

    Jika Anda mengalami error ketidakcocokan signature 403 saat menggunakan Browser.js untuk mengunggah file, biasanya karena browser secara otomatis menambahkan header permintaan Content-Type, dan header ini tidak disertakan saat URL yang ditandatangani sebelumnya dihasilkan. Ketidakcocokan ini menyebabkan kegagalan verifikasi signature. Untuk mengatasi masalah ini, Anda harus menentukan header permintaan Content-Type saat menghasilkan URL yang ditandatangani sebelumnya.

    <!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 (Java SDK)</h1>
    
        <input type="file" id="fileInput" />
        <button id="uploadButton">Unggah File</button>
    
        <script>
            // Ganti ini dengan URL yang ditandatangani sebelumnya yang 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 path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh secara default.
    var filePath = "C:\\Users\\demo.txt";
    // Ganti <signedUrl> dengan URL yang diotorisasi.
    var presignedUrl = "<signedUrl>";
    
    // Buat client HTTP dan buka stream 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 mengatur parameter header, seperti metadata pengguna dan kelas penyimpanan, saat menghasilkan URL yang ditandatangani sebelumnya, Anda juga harus mengirim parameter ini ke server saat menggunakan URL tersebut untuk mengunggah file. Error signature akan dilaporkan jika parameter yang dikirim ke server tidak konsisten dengan parameter yang ditandatangani.
    // 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 pengguna kustom. Metadata pengguna kustom harus sama dengan informasi 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");
    
    // Cetak 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 respons.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Unggah berhasil! Kode status: {response.StatusCode}");
        Console.WriteLine("Header respons:");
        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 respons: " + responseContent);
    }

    C++

    #include <iostream>
    #include <fstream>
    #include <curl/curl.h>
    #include <map>
    #include <string>
    
    // Fungsi callback untuk menangani 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) {
            // Atur URL.
            curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str());
    
            // Atur metode permintaan menjadi PUT.
            curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    
            // Buka file.
            FILE* file = fopen(filePath.c_str(), "rb");
            if (!file) {
                std::cerr << "Tidak dapat 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 penanganan respons.
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
    
            // Jalankan 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 yang dikembalikan untuk unggahan: " << responseCode << std::endl;
                if (responseCode == 200) {
                    std::cout << "Unggah berhasil 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 yang diotorisasi.
        std::string signedUrl = "<signedUrl>";
    
        // Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh 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 pengguna kustom. Metadata pengguna kustom harus sama dengan informasi 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 yang diotorisasi.
            String signedUrl = "<signedUrl>";
    
            // Tentukan path lengkap file lokal. Jika Anda tidak menentukan path lokal, file akan diunggah dari path proyek program contoh 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 pengguna kustom. Metadata pengguna kustom harus sama dengan informasi 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 pengguna 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 respons.
                    int responseCode = connection.getResponseCode();
                    Log.d(TAG, "Kode status yang dikembalikan untuk unggahan: " + responseCode);
                    if (responseCode == 200) {
                        Log.d(TAG, "Unggah berhasil 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, "Unggah berhasil.", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SignUrlUploadActivity.this, "Unggah gagal.", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
    

Gunakan URL yang ditandatangani sebelumnya untuk unggah multi-bagian

Untuk mengunggah objek dalam beberapa bagian menggunakan URL yang ditandatangani sebelumnya, Anda harus mengonfigurasi ukuran bagian dan menghasilkan URL yang ditandatangani sebelumnya untuk setiap bagian. Kode contoh berikut menggunakan URL yang ditandatangani sebelumnya untuk unggah multi-bagian:

package main

import (
	"crypto/md5"
	"encoding/base64"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
	// Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		log.Printf("Error:%v", err)
	}
	// Buat instans OSSClient.
	// Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com.
	client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
	if err != nil {
		log.Printf("Error:%v", err)
	}
	bucketName := "bucket_name"

	bucket, err := client.Bucket(bucketName)
	if err != nil {
		log.Printf("Error:%v", err)
	}
	// Tentukan path lengkap objek. Jangan sertakan nama bucket dalam path lengkap.
	objectName := "example.txt"
	// Tentukan path lengkap file lokal yang ingin Anda unggah. Jika path file lokal tidak ditentukan, file lokal akan diunggah dari path proyek tempat program contoh berada.
	localFile := "D:\\download\\demo.txt"

	// Pisahkan file lokal menjadi tiga bagian.
	chunks, err := oss.SplitFileByPartNum(localFile, 3)
	fd, err := os.Open(localFile)
	defer fd.Close()
	// Langkah 1: Mulai tugas unggah multi-bagian dan atur kelas penyimpanan objek menjadi Standard.
	imur, err := bucket.InitiateMultipartUpload(objectName)
	// Langkah 2: Unggah bagian-bagiannya.
	var options []oss.Option

	for _, chunk := range chunks {
		// Konfigurasikan verifikasi MD5.
		buf := make([]byte, chunk.Size)
		fd.ReadAt(buf, chunk.Size)
		sum := md5.Sum(buf)
		b64 := base64.StdEncoding.EncodeToString(sum[:])
		options = []oss.Option{
			oss.ContentMD5(b64),
		}

		options = append(options, oss.AddParam("partNumber", strconv.Itoa(chunk.Number)))
		options = append(options, oss.AddParam("uploadId", imur.UploadID))
		// Hasilkan URL yang ditandatangani sebelumnya.
		signedURL, err := bucket.SignURL(objectName, oss.HTTPPut, 60, options...)
		if err != nil {
			log.Printf("Error:%v", err)
		}
		fmt.Printf("Presigned URL: %s\n", signedURL)
		err = bucket.PutObjectWithURL(signedURL, strings.NewReader(string(buf)), options...)
		if err != nil {
			log.Printf("Error:%v", err)
		}
	}

	lsRes, err := bucket.ListUploadedParts(imur)
	if err != nil {
		log.Printf("Error:%v	}

	// Telusuri bagian-bagian dan isi partETags.
	var parts []oss.UploadPart
	for _, p := range lsRes.UploadedParts {
		parts = append(parts, oss.UploadPart{XMLName: p.XMLName, PartNumber: p.PartNumber, ETag: p.ETag})
	}

	// Langkah 3: Selesaikan tugas unggah multi-bagian.
	_, err = bucket.CompleteMultipartUpload(imur, parts)
	if err != nil {
		log.Printf("Error:%v", err)
	}
	fmt.Println("Diunggah")
}

FAQ

Saat saya menggunakan URL yang ditandatangani sebelumnya untuk mengunggah file lokal, apakah unggahan file akan gagal jika URL tersebut kedaluwarsa selama proses unggah?

Tidak, unggahan file tidak akan gagal meskipun URL yang ditandatangani sebelumnya kedaluwarsa selama proses unggah.

URL yang ditandatangani sebelumnya dapat digunakan selama periode validitasnya, yang ditentukan oleh durasi lebih pendek antara validitas token dan validitas signature.

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

Tidak, Anda tidak perlu menentukan header permintaan dan metadata pengguna.

Header permintaan dan metadata pengguna adalah parameter opsional. Jika Anda tidak menentukannya, hapus kode terkait pada contoh di atas.

Referensi

  • Untuk kode contoh lengkap yang mengunggah file menggunakan URL yang ditandatangani sebelumnya, kunjungi GitHub.

  • Untuk informasi lebih lanjut tentang operasi API yang menandatangani URL sebelumnya, lihat SignURL.