All Products
Search
Document Center

Object Storage Service:Unduh objek menggunakan URL yang ditandatangani (Go SDK V1)

Last Updated:Nov 29, 2025

Secara default, objek dalam bucket Object Storage Service (OSS) bersifat privat dan hanya dapat diakses oleh pemiliknya. Anda dapat menggunakan Go SDK untuk menghasilkan URL yang ditandatangani untuk permintaan GET, sehingga pengguna lain dapat mengunduh objek tersebut secara sementara. URL ini dapat digunakan beberapa kali hingga masa berlakunya habis. Setelah kedaluwarsa, Anda harus membuat URL baru.

Perhatian

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

  • Contoh dalam topik ini menunjukkan cara membaca kredensial akses dari variabel lingkungan. Untuk informasi lebih lanjut tentang konfigurasi kredensial akses, lihat Configure access credentials (Go SDK V1).

  • Topik ini membuat instans OSSClient menggunakan titik akhir OSS. Jika Anda ingin membuat instans OSSClient menggunakan nama domain kustom atau Security Token Service (STS), lihat Configuration examples for common scenarios.

  • Anda tidak memerlukan izin khusus untuk menghasilkan URL yang ditandatangani. Namun, agar pihak ketiga dapat mengunduh objek menggunakan URL tersebut, pengguna yang menghasilkan URL harus memiliki izin oss:GetObject. Untuk informasi lebih lanjut tentang pemberian izin, lihat Grant custom permissions to a RAM user.

  • Contoh dalam topik ini menggunakan URL yang ditandatangani versi V4, yang memiliki periode validitas maksimum 7 hari. Untuk informasi lebih lanjut, lihat Signature V4 (recommended).

Prosedur

Langkah-langkah berikut menjelaskan cara mengunduh objek menggunakan URL yang telah ditandatangani:

Kode contoh

  1. Pemilik objek menghasilkan URL yang ditandatangani untuk permintaan GET.

    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\n", err)
    	}
    
    	// Buat instans OSSClient.
    	// Setel yourEndpoint ke titik akhir bucket. Misalnya, untuk bucket di wilayah China (Hangzhou), setel titik akhir ke https://oss-cn-hangzhou.aliyuncs.com. Untuk wilayah lain, sesuaikan titik akhirnya.
    	// Setel yourRegion ke wilayah tempat bucket berada. Misalnya, untuk bucket di wilayah China (Hangzhou), setel wilayah ke cn-hangzhou. Untuk wilayah lain, sesuaikan wilayahnya.
    	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
    	clientOptions = append(clientOptions, oss.Region("cn-hangzhou"))
    	// Setel versi signature.
    	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
    	client, err := oss.New("yourEndpoint", "", "", clientOptions...)
    	if err != nil {
    		log.Printf("Error: %v\n", err)
    	}
    
    	// Tentukan nama bucket, misalnya examplebucket.
    	bucketName := "examplebucket"
    	// Tentukan nama objek, misalnya exampleobject.txt. Nama objek tidak boleh mengandung nama bucket.
    	objectName := "exampleobject.txt"
    	// Unduh objek ke file lokal dan simpan ke jalur lokal yang ditentukan. Jika file lokal yang ditentukan sudah ada, file tersebut akan ditimpa. Jika file belum ada, file tersebut akan dibuat.
    	bucket, err := client.Bucket(bucketName)
    	if err != nil {
    		log.Printf("Error: %v\n", err)
    	}
    
    	// Hasilkan URL yang ditandatangani untuk mengunduh objek dan atur periode validitas URL tersebut menjadi 600 detik.
    	signedURL, err := bucket.SignURL(objectName, oss.HTTPGet, 600)
    	if err != nil {
    		log.Printf("Error: %v\n", err)
    	}
    	log.Printf("Sign Url:%s\n", signedURL)
    }
    
  2. Pengguna lain mengunduh objek menggunakan URL yang ditandatangani tersebut.

    curl

    curl -SO "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"

    Java

    import java.io.BufferedInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class Demo {
        public static void main(String[] args) {
            // Ganti dengan URL yang telah ditandatangani sebelumnya untuk permintaan GET yang dihasilkan.
            String fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************";
            // Masukkan jalur tujuan untuk menyimpan file, termasuk nama file dan ekstensinya.
            String savePath = "C:/downloads/myfile.txt";
    
            try {
                downloadFile(fileURL, savePath);
                System.out.println("Download completed!");
            } catch (IOException e) {
                System.err.println("Error during download: " + e.getMessage());
            }
        }
    
        private static void downloadFile(String fileURL, String savePath) throws IOException {
            URL url = new URL(fileURL);
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            httpConn.setRequestMethod("GET");
    
            // Periksa kode respons.
            int responseCode = httpConn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // Aliran input.
                InputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
                // Aliran output.
                FileOutputStream outputStream = new FileOutputStream(savePath);
    
                byte[] buffer = new byte[4096]; // Buffer.
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
    
                outputStream.close();
                inputStream.close();
            } else {
                System.out.println("No file to download. Server replied HTTP code: " + responseCode);
            }
            httpConn.disconnect();
        }
    }

    Node.js

    const https = require('https');
    const fs = require('fs');
    
    const fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************";
    const savePath = "C:/downloads/myfile.txt";
    
    https.get(fileURL, (response) => {
        if (response.statusCode === 200) {
            const fileStream = fs.createWriteStream(savePath);
            response.pipe(fileStream);
            
            fileStream.on('finish', () => {
                fileStream.close();
                console.log("Download completed!");
            });
        } else {
            console.error(`Download failed. Server responded with code: ${response.statusCode}`);
        }
    }).on('error', (err) => {
        console.error("Error during download:", err.message);
    });

    Python

    import requests
    
    file_url = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"
    save_path = "C:/downloads/myfile.txt"
    
    try:
        response = requests.get(file_url, stream=True)
        if response.status_code == 200:
            with open(save_path, 'wb') as f:
                for chunk in response.iter_content(4096):
                    f.write(chunk)
            print("Download completed!")
        else:
            print(f"No file to download. Server replied HTTP code: {response.status_code}")
    except Exception as e:
        print("Error during download:", e)

    Go

    package main
    
    import (
        "io"
        "net/http"
        "os"
    )
    
    func main() {
        fileURL := "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"
        savePath := "C:/downloads/myfile.txt"
    
        response, err := http.Get(fileURL)
        if err != nil {
            panic(err)
        }
        defer response.Body.Close()
    
        if response.StatusCode == http.StatusOK {
            outFile, err := os.Create(savePath)
            if err != nil {
                panic(err)
            }
            defer outFile.Close()
    
            _, err = io.Copy(outFile, response.Body)
            if err != nil {
                panic(err)
            }
            println("Download completed!")
        } else {
            println("No file to download. Server replied HTTP code:", response.StatusCode)
        }
    }

    JavaScript

    const fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************";
    const savePath = "C:/downloads/myfile.txt"; // Nama file yang akan digunakan untuk unduhan.
    
    fetch(fileURL)
        .then(response => {
            if (!response.ok) {
                throw new Error(`Server replied HTTP code: ${response.status}`);
            }
            return response.blob(); // Konversi respons menjadi blob.
        })
        .then(blob => {
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download = savePath; // Atur nama file yang diunduh.
            document.body.appendChild(link); // Langkah ini memastikan tautan ada dalam dokumen.
            link.click(); // Simulasikan klik pada tautan unduhan.
            link.remove(); // Hapus tautan setelah selesai.
            console.log("Download completed!");
        })
        .catch(error => {
            console.error("Error during download:", error);
        });

    Android-Java

    import android.os.AsyncTask;
    import android.os.Environment;
    import java.io.BufferedInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class DownloadTask extends AsyncTask<String, String, String> {
        @Override
        protected String doInBackground(String... params) {
            String fileURL = params[0];
            String savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/myfile.txt"; // Jalur penyimpanan yang dimodifikasi.
            try {
                URL url = new URL(fileURL);
                HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
                httpConn.setRequestMethod("GET");
                int responseCode = httpConn.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    InputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
                    FileOutputStream outputStream = new FileOutputStream(savePath);
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    outputStream.close();
                    inputStream.close();
                    return "Download completed!";
                } else {
                    return "No file to download. Server replied HTTP code: " + responseCode;
                }
            } catch (Exception e) {
                return "Error during download: " + e.getMessage();
            }
        }
    }

    Objective-C

    #import <Foundation/Foundation.h>
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // Definisikan URL file dan jalur penyimpanan (ubah ke jalur yang valid).
            NSString *fileURL = @"https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************";
            NSString *savePath = @"/Users/your_username/Desktop/myfile.txt"; // Ganti dengan username Anda.
    
            // Buat objek URL.
            NSURL *url = [NSURL URLWithString:fileURL];
    
            // Buat tugas unduhan.
            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                // Penanganan error.
                if (error) {
                    NSLog(@"Error during download: %@", error.localizedDescription);
                    return;
                }
    
                // Periksa data.
                if (!data) {
                    NSLog(@"No data received.");
                    return;
                }
    
                // Simpan file.
                NSError *writeError = nil;
                BOOL success = [data writeToURL:[NSURL fileURLWithPath:savePath] options:NSDataWritingAtomic error:&writeError];
                if (success) {
                    NSLog(@"Download completed!");
                } else {
                    NSLog(@"Error saving file: %@", writeError.localizedDescription);
                }
            }];
    
            // Mulai tugas.
            [task resume];
    
            // Pertahankan thread utama tetap berjalan agar permintaan asinkron dapat diselesaikan.
            [[NSRunLoop currentRunLoop] run];
        }
        return 0;
    }

Skenario lain

Hasilkan URL yang ditandatangani untuk permintaan GET guna mengunduh versi tertentu dari file

Kode contoh berikut menunjukkan cara menentukan versi objek saat menghasilkan URL yang ditandatangani untuk permintaan GET, sehingga pengguna lain dapat mengunduh versi tertentu dari objek tersebut.

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 instans OSSClient.
	// Setel yourEndpoint ke titik akhir bucket. Misalnya, untuk bucket di wilayah China (Hangzhou), setel titik akhir ke https://oss-cn-hangzhou.aliyuncs.com. Untuk wilayah lain, sesuaikan titik akhirnya.
	// Setel yourRegion ke wilayah tempat bucket berada. Misalnya, untuk bucket di wilayah China (Hangzhou), setel wilayah ke cn-hangzhou. Untuk wilayah lain, sesuaikan wilayahnya.
	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
	clientOptions = append(clientOptions, oss.Region("cn-hangzhou"))
	// Setel versi signature.
	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
	client, err := oss.New("yourEndpoint", "", "", clientOptions...)
	if err != nil {
		log.Printf("Error: %v", err)
	}

	// Tentukan nama bucket, misalnya examplebucket.
	bucketName := "examplebucket"
	// Tentukan jalur lengkap objek, misalnya exampledir/exampleobject.txt. Jalur lengkap tidak boleh mengandung nama bucket.
	objectName := "exampledir/exampleobject.txt"
	// Unduh objek ke file lokal dan simpan ke jalur lokal yang ditentukan. Jika file lokal yang ditentukan sudah ada, file tersebut akan ditimpa. Jika file belum ada, file tersebut akan dibuat.
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		log.Printf("Error: %v", err)
	}

	// Tentukan ID versi file yang akan diunduh.
	options := []oss.Option{
		oss.VersionId("CAEQEhiBgIDmgPf8mxgiIDA1YjZlNDIxY2ZmMzQ1MmU5MTM1Y2M4Yzk4******"),
	}

	// Hasilkan URL yang ditandatangani untuk mengunduh objek dan atur periode validitas URL tersebut menjadi 600 detik.
	signedURL, err := bucket.SignURL(objectName, oss.HTTPGet, 600, options...)
	if err != nil {
		log.Printf("Error: %v", err)
	}
	log.Printf("Sign Url:%s\n", signedURL)
}

Unduh file menggunakan URL yang ditandatangani dengan request header tertentu

Jika Anda menentukan request header saat menghasilkan URL yang ditandatangani untuk permintaan GET, Anda harus menyertakan request header yang sama dalam permintaan GET yang menggunakan URL tersebut. Jika tidak, permintaan akan gagal karena kesalahan signature.

  1. Hasilkan URL yang ditandatangani untuk permintaan GET yang mencakup request header.

    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 instans OSSClient.
    	// Setel yourEndpoint ke titik akhir bucket. Misalnya, untuk bucket di wilayah China (Hangzhou), setel titik akhir ke https://oss-cn-hangzhou.aliyuncs.com. Untuk wilayah lain, sesuaikan titik akhirnya.
    	// Setel yourRegion ke wilayah tempat bucket berada. Misalnya, untuk bucket di wilayah China (Hangzhou), setel wilayah ke cn-hangzhou. Untuk wilayah lain, sesuaikan wilayahnya.
    	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
    	clientOptions = append(clientOptions, oss.Region("cn-hangzhou"))
    	// Setel versi signature.
    	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
    	client, err := oss.New("yourEndpoint", "", "", clientOptions...)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    
    	// Tentukan nama bucket, misalnya examplebucket.
    	bucketName := "examplebucket"
    	// Tentukan jalur lengkap objek, misalnya exampledir/exampleobject.txt. Jalur lengkap tidak boleh mengandung nama bucket.
    	objectName := "exampledir/exampleobject.txt"
    	// Unduh objek ke file lokal dan simpan ke jalur lokal yang ditentukan. Jika file lokal yang ditentukan sudah ada, file tersebut akan ditimpa. Jika file belum ada, file tersebut akan dibuat.
    	bucket, err := client.Bucket(bucketName)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    
    	// Jika Anda ingin menggunakan URL yang ditandatangani dengan parameter opsional di antarmuka depan, pastikan ContentType yang ditetapkan saat menghasilkan URL di server sama dengan ContentType yang ditetapkan di antarmuka depan.
    	options := []oss.Option{
    		oss.ContentType("text/plain; charset=utf8"),
    	}
    
    	// Hasilkan URL yang ditandatangani untuk mengunduh objek dan atur periode validitas URL tersebut menjadi 600 detik.
    	signedURL, err := bucket.SignURL(objectName, oss.HTTPGet, 600, options...)
    	if err != nil {
    		log.Printf("Error: %v", err)
    	}
    	log.Printf("Sign Url:%s\n", signedURL)
    }
    
  2. Unduh objek menggunakan URL yang ditandatangani dan sertakan request header tersebut.

    curl -X GET "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241113T093321Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************&x-oss-signature=ed5a******************************************************" \
    -H "Content-Type: text/plain; charset=utf8" \
    -o "myfile.txt"
    package main
    
    import (
    	"io"
    	"log"
    	"net/http"
    	"os"
    )
    
    func main() {
    	// Tentukan URL yang telah ditandatangani yang dihasilkan.
    	url := "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"
    
    	// Gunakan URL yang telah ditandatangani yang dihasilkan untuk mengunduh file menggunakan metode HTTP GET.
    	req, err := http.NewRequest(http.MethodGet, url, nil)
    	if err != nil {
    		log.Fatalf("Failed to create PUT request: %v", err)
    	}
    
    	//Setel header permintaan Content-Type.
    	req.Header.Set("Content-Type", "text/plain")
    
    	// Kirim permintaan.
    	client := &http.Client{}
    	resp, err := client.Do(req)
    	if err != nil {
    		log.Fatalf("Failed to upload file: %v", err)
    	}
    	defer resp.Body.Close()
    
    	// Definisikan jalur file lokal yang akan ditulis.
    	filePath := "downloadfile.txt"
    
    	// Buat atau buka file lokal.
    	file, err := os.Create(filePath)
    	if err != nil {
    		log.Fatalf("failed to create or open file: %v", err)
    	}
    	defer file.Close() // Pastikan file ditutup saat fungsi berakhir.
    
    	// Gunakan io.Copy untuk menulis konten file ke file lokal.
    	n, err := io.Copy(file, resp.Body)
    	if err != nil {
    		log.Fatalf("failed to read object %v", err)
    	}
    
    	// Tutup badan respons.
    	err = resp.Body.Close()
    	if err != nil {
    		log.Printf("failed to close response body: %v", err)
    	}
    
    	log.Printf("wrote %d bytes to file: %s\n", n, filePath)
    }
    

Referensi

  • Untuk kode contoh lengkap tentang cara mengunduh objek menggunakan URL yang ditandatangani, lihat GitHub example.

  • Untuk informasi lebih lanjut tentang operasi API yang dapat dipanggil untuk mengunduh objek menggunakan URL yang ditandatangani, lihat SignURL.