全部产品
Search
文档中心

Object Storage Service:Gunakan URL yang ditandatangani untuk mengunggah file dengan OSS SDK untuk Go

更新时间:Aug 08, 2025

Secara default, daftar kontrol akses (ACL) objek dalam bucket Object Storage Service (OSS) bersifat pribadi, dan hanya pemilik objek yang memiliki izin untuk mengaksesnya. Anda dapat menggunakan OSS SDK untuk Go untuk menghasilkan URL yang ditandatangani, yang kemudian dapat dibagikan kepada pengguna untuk mengizinkan mereka mengunggah objek. Saat menghasilkan URL yang ditandatangani, Anda dapat menentukan periode validitasnya untuk membatasi waktu pengguna dapat mengunggah objek. Selama periode validitas, pengguna dapat menggunakan URL tersebut untuk mengunggah objek ke bucket berkali-kali. Setelah periode validitas berakhir, pengguna tidak dapat lagi menggunakan URL yang ditandatangani untuk mengunggah objek. Untuk memperpanjang akses, Anda dapat menghasilkan ulang URL yang ditandatangani.

Catatan Penggunaan

  • Dalam topik ini, titik akhir publik wilayah China (Hangzhou) digunakan. Untuk mengakses OSS dari layanan Alibaba Cloud lainnya di wilayah yang sama, gunakan titik akhir internal. Untuk detail tentang wilayah dan titik akhir yang didukung, lihat Wilayah dan Titik Akhir.

  • Dalam topik ini, kredensial akses diperoleh dari variabel lingkungan. Untuk informasi lebih lanjut tentang cara mengonfigurasi kredensial akses, lihat Konfigurasikan Kredensial Akses.

  • Dalam topik ini, instance OSSClient dibuat menggunakan titik akhir OSS. Jika ingin membuat instance OSSClient menggunakan nama domain kustom atau Layanan Token Keamanan (STS), lihat Contoh Konfigurasi untuk Skenario Umum.

  • Anda tidak memerlukan izin tertentu 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 Berikan Izin kepada Pengguna RAM Menggunakan Kebijakan Kustom.

  • Dalam topik ini, algoritma tanda tangan V4 digunakan untuk menghasilkan URL yang ditandatangani dengan periode validitas hingga 7 hari. Untuk informasi lebih lanjut, lihat (Direkomendasikan) Sertakan Tanda Tangan V4 dalam URL.

Proses

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

Gunakan URL yang Ditandatangani untuk Unggahan Sederhana

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

    package main
    
    import (
    	"log"
    
    	"github.com/aliyun/aliyun-oss-go-sdk/oss"
    )
    
    func main() {
    	// Dapatkan 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 instance OSSClient.
    	// Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir ke https://oss-cn-hangzhou.aliyuncs.com.
    	// Tentukan wilayah bucket. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur wilayah ke 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 jalur lengkap objek. Contoh: exampleobject.txt. Jangan sertakan nama bucket dalam jalur lengkap.
    	objectName := "exampleobject.txt"
    	bucket, err := client.Bucket(bucketName)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    
    	// Hasilkan URL yang ditandatangani dan atur periode validitas URL yang ditandatangani 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 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 otorisasi.
            URL signedUrl = new URL("<signedUrl>");
    
            // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file akan 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("Diunggah berhasil menggunakan pustaka 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 respons.
    	body, err := io.ReadAll(resp.Body)
    	if err != nil {
    		return fmt.Errorf("Gagal membaca respons: %w", err)
    	}
    
    	fmt.Printf("Kode status yang dikembalikan: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Diunggah berhasil menggunakan pustaka 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 akan 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("Diunggah berhasil menggunakan pustaka 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 akan 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('Diunggah berhasil menggunakan pustaka 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 akan 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 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 selama 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 akan 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 respons.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Diunggah 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 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 << "Diunggah berhasil menggunakan pustaka 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 akan 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, "Diunggah berhasil menggunakan pustaka 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 akan 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 File

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

    package main
    
    import (
    	"log"
    
    	"github.com/aliyun/aliyun-oss-go-sdk/oss"
    )
    
    func main() {
    	// Dapatkan 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 instance OSSClient.
    	// Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir ke https://oss-cn-hangzhou.aliyuncs.com.
    	// Tentukan wilayah bucket. Misalnya, jika bucket Anda berada di wilayah China (Hangzhou), atur wilayah ke 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 jalur lengkap objek. Contoh: exampleobject.txt. Jangan sertakan nama bucket dalam jalur 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 yang berisi parameter kustom di frontend, Anda harus menentukan jenis konten yang sama dengan yang ditentukan di sini untuk menghasilkan URL yang ditandatangani.
    	options := []oss.Option{
    		oss.Meta("key1", "value1"),
    		oss.Meta("key2", "value2"),
    		oss.ContentType("text/plain; charset=utf8"),
    	}
    
    	// Hasilkan URL yang ditandatangani dan atur periode validitas URL yang ditandatangani 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 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

    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 akan diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
            String pathName = "C:\\Users\\demo.txt";
    
            // Tetapkan 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");
    
            // Tetapkan 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("Diunggah berhasil menggunakan pustaka 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
    	}
    
    	// Tetapkan header permintaan.
    	for key, value := range headers {
    		req.Header.Set(key, value)
    	}
    
    	// Tetapkan 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 respons.
    	fmt.Printf("Kode status yang dikembalikan: %d\n", resp.StatusCode)
    	if resp.StatusCode == 200 {
    		fmt.Println("Diunggah berhasil menggunakan pustaka 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 akan diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
    	filePath := "C:\\Users\\demo.txt"
    
    	// Tetapkan 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",
    	}
    
    	// Tetapkan 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("Diunggah berhasil menggunakan pustaka 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 akan diunggah dari direktori tempat skrip berada secara default.
        file_path = "C:\\Users\\demo.txt"
    
        # Tetapkan 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"
        }
    
        # Tetapkan 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("Diunggah berhasil menggunakan pustaka 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 akan diunggah dari direktori tempat skrip berada secara default.
        const filePath = "C:\\Users\\demo.txt";
    
        // Tetapkan 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"
        };
    
        // Tetapkan 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 selama unggah:', error);
                        alert('Unggah gagal: ' + error.message);
                    }
                } else {
                    alert('Silakan pilih file untuk diunggah.');
                }
            });
    
            const upload = async (file, presignedUrl) => {
                const headers = {
                    "Content-Type": "text/plain;charset=utf8",
                    'x-oss-storage-class': 'Standard',
                    'x-oss-meta-key1': 'value1',
                    'x-oss-meta-key2': 'value2'
                };
    
                const response = await fetch(presignedUrl, {
                    method: 'PUT',
                    headers: headers,
                    body: file
                });
    
                if (!response.ok) {
                    throw new Error(`Unggah gagal, status: ${response.status}`);
                }
    
                alert('File berhasil diunggah');
                console.log('File berhasil diunggah');
            };
        </script>
    </body>
    </html>

    C#

    using System.Net.Http.Headers;
    
    // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file akan 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.
    // Tetapkan 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.       
    // Tetapkan 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 respons.
    if (response.IsSuccessStatusCode)
    {
        Console.WriteLine($"Diunggah 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 yang digunakan untuk memproses respons HTTP.
    size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
        size_t totalSize = size * nmemb;
        output->append((char*)contents, totalSize);
        return totalSize;
    }
    
    void uploadFile(const std::string& signedUrl, const std::string& filePath, const std::map<std::string, std::string>& headers, const std::map<std::string, std::string>& metadata) {
        CURL* curl;
        CURLcode res;
        std::string readBuffer;
    
        curl_global_init(CURL_GLOBAL_DEFAULT);
        curl = curl_easy_init();
    
        if (curl) {
            // 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 respons.
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
    
            // Eksekusi permintaan.
            res = curl_easy_perform(curl);
    
            // Periksa respons.
            if (res != CURLE_OK) {
                std::cerr << "curl_easy_perform() gagal: " << curl_easy_strerror(res) << std::endl;
            } else {
                long responseCode;
                curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
                std::cout << "Kode status yang dikembalikan: " << responseCode << std::endl;
                if (responseCode == 200) {
                    std::cout << "Diunggah berhasil menggunakan pustaka 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 akan diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
        std::string filePath = "C:\\Users\\demo.txt";
    
        // Tetapkan 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"}
        };
    
        // Tetapkan 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 akan diunggah dari jalur yang sesuai dengan proyek program sampel secara default.
            String pathName = "/storage/emulated/0/demo.txt";
    
            // Tetapkan 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");
    
            // Tetapkan 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);
    
                    // Tetapkan header permintaan.
                    for (Entry<String, String> header : headers.entrySet()) {
                        connection.setRequestProperty(header.getKey(), header.getValue());
                    }
    
                    // Tetapkan 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 respons.
                    int responseCode = connection.getResponseCode();
                    Log.d(TAG, "Kode status yang dikembalikan: " + responseCode);
                    if (responseCode == 200) {
                        Log.d(TAG, "Diunggah berhasil menggunakan pustaka 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, "Diunggah berhasil.", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SignUrlUploadActivity.this, "Unggah gagal.", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
    

Gunakan URL yang Ditandatangani untuk Unggahan Multi-Bagian

Untuk mengunggah objek dalam beberapa bagian menggunakan URL yang ditandatangani, Anda harus mengonfigurasi ukuran bagian dan menghasilkan URL yang ditandatangani untuk setiap bagian. Contoh kode berikut menggunakan URL yang ditandatangani untuk unggahan multi-bagian:

package main

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

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

func main() {
	// Dapatkan 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 instance OSSClient.
	// Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir ke 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 jalur lengkap objek. Jangan sertakan nama bucket dalam jalur lengkap.
	objectName := "example.txt"
	// Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal akan diunggah dari jalur proyek tempat program sampel 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 unggahan multi-bagian dan atur kelas penyimpanan objek ke 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.
		signedURL, err := bucket.SignURL(objectName, oss.HTTPPut, 60, options...)
		if err != nil {
			log.Printf("Error:%v", err)
		}
		fmt.Printf("URL yang Ditandatangani: %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", err)
	}

	// Lintasi 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 unggahan multi-bagian.
	_, err = bucket.CompleteMultipartUpload(imur, parts)
	if err != nil {
		log.Printf("Error:%v", err)
	}
	fmt.Println("Diunggah")
}

Tanya Jawab Umum

Ketika saya menggunakan URL yang ditandatangani untuk mengunggah file lokal, apakah pengunggahan file akan gagal jika URL yang ditandatangani kedaluwarsa selama proses pengunggahan?

Tidak, pengunggahan file tidak akan gagal meskipun URL yang ditandatangani kedaluwarsa selama proses pengunggahan.

URL yang ditandatangani dapat digunakan dalam periode validitasnya, yang ditentukan oleh durasi yang lebih pendek antara masa berlaku token dan masa berlaku tanda tangan.

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?

Tidak, 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-contoh sebelumnya.

Referensi

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

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