すべてのプロダクト
Search
ドキュメントセンター

Object Storage Service:署名付き URL を使用してオブジェクトをダウンロードする (Go SDK V2)

最終更新日:Nov 09, 2025

デフォルトでは、Object Storage Service (OSS) バケット内のオブジェクトのアクセス制御リスト (ACL) は非公開です。オブジェクト所有者のみがオブジェクトにアクセスする権限を持っています。このトピックでは、OSS SDK for Go を使用して、ユーザーが HTTP GET リクエストを使用してオブジェクトを一時的にダウンロードできる署名付き URL を生成する方法について説明します。URL は指定された期間有効で、その間ユーザーはオブジェクトを複数回ダウンロードできます。URL の有効期限が切れた後、ユーザーは新しい署名付き URL を取得する必要があります。

注意

  • このトピックのサンプルコードでは、中国 (杭州) リージョンのリージョン ID cn-hangzhou を使用します。デフォルトでは、パブリックエンドポイントを使用してバケットリソースにアクセスします。同じリージョン内の他の Alibaba Cloud サービスからバケットリソースにアクセスする場合は、内部エンドポイントを使用します。OSS のリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。

  • このトピックでは、アクセス資格情報は環境変数から取得されます。アクセス資格情報の設定方法の詳細については、「アクセス資格情報の設定」をご参照ください。

  • 署名付き URL を生成するために特定の権限は必要ありません。ただし、他のユーザーが署名付き URL を使用してオブジェクトをダウンロードできるようにするには、oss:GetObject 権限が必要です。詳細については、「RAM ポリシーの一般的な例」をご参照ください。

  • このトピックでは、V4 署名付き URL が使用されます。これらの URL の最大有効期間は 7 日間です。詳細については、「(推奨) URL に V4 署名を含める」をご参照ください。

プロセス

次のフローチャートは、署名付き URL を使用してオブジェクトをダウンロードする方法を示しています。

メソッド定義

特定の操作を呼び出して、バケット内のオブジェクトへの一時的なアクセス権限を付与する署名付き URL を生成できます。署名付き URL は、有効期限が切れる前に複数回使用できます。

次のコードは、presign 操作の構文を示しています。

func (c *Client) Presign(ctx context.Context, request any, optFns ...func(*PresignOptions)) (result *PresignResult, err error)

リクエストパラメーター

パラメーター

説明

ctx

context.Context

リクエストのコンテキスト。

request

*GetObjectRequest

署名付き URL の生成に使用される API 操作の名前。

optFns

...func(*PresignOptions)

署名付き URL の有効期間。このパラメーターを指定しない場合、署名付き URL はデフォルト値の 15 分を使用します。このパラメーターはオプションです。

次の表に、PresignOptions のオプションを示します。

オプション

説明

Expires

time.Duration

署名付き URL の有効期間。たとえば、有効期間を 30 分に設定する場合は、Expires を 30 * time.Minute に設定します。

Expiration

time.Time

署名付き URL の絶対有効期限。

重要

V4 署名アルゴリズムを使用する場合、有効期間は最大 7 日間です。Expiration と Expires の両方を指定した場合、Expiration が優先されます。

レスポンスパラメーター

応答プロパティ

説明

result

*PresignResult

署名付き URL、HTTP メソッド、有効期間、リクエストで指定されたリクエストヘッダーなど、返される結果。

err

error

リクエストのステータス。リクエストが失敗した場合、err の値は nil にはなりません。

次の表に、PresignResult のレスポンスパラメーターを示します。

パラメーター

説明

Method

string

操作に対応する HTTP メソッド。たとえば、GetObject 操作の HTTP メソッドは GET です。

URL

string

署名付き URL。

Expiration

time.Time

署名付き URL の有効期限。

SignedHeaders

map[string]string

リクエストで指定されたリクエストヘッダー。たとえば、Content-Type ヘッダーの値が指定されている場合、Content-Type に関する情報が返されます。

サンプルコード

  1. 次のサンプルコードは、オブジェクト所有者が HTTP GET リクエストを許可する署名付き URL を生成する方法を示しています。

    package main
    
    import (
    	"context"
    	"flag"
    	"log"
    	"time"
    
    	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
    	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
    )
    
    // グローバル変数を定義します。
    var (
    	region     string // バケットが配置されているリージョン。
    	bucketName string // バケットの名前。
    	objectName string // オブジェクトの名前。
    )
    
    // init 関数は、コマンドラインパラメーターを初期化するために使用されます。
    func init() {
    	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
    	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
    	flag.StringVar(&objectName, "object", "", "The name of the object.")
    }
    
    func main() {
    	// コマンドラインパラメーターを解析します。
    	flag.Parse()
    
    	// バケット名が空かどうかを確認します。
    	if len(bucketName) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, bucket name required")
    	}
    
    	// リージョンが空かどうかを確認します。
    	if len(region) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, region required")
    	}
    
    	// オブジェクト名が空かどうかを確認します。
    	if len(objectName) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, object name required")
    	}
    
    	// デフォルトの構成をロードし、資格情報プロバイダーとリージョンを指定します。
    	cfg := oss.LoadDefaultConfig().
    		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
    		WithRegion(region)
    
    	// OSS クライアントを作成します。
    	client := oss.NewClient(cfg)
    
    	// GetObject リクエストの署名付き URL を生成します。
    	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
    		Bucket: oss.Ptr(bucketName),
    		Key:    oss.Ptr(objectName),
    	},
    		oss.PresignExpires(10*time.Minute),
    	)
    	if err != nil {
    		log.Fatalf("failed to get object presign %v", err)
    	}
    
    	log.Printf("リクエストメソッド:%v\n", result.Method)
    	log.Printf("リクエストの有効期限:%v\n", result.Expiration)
    	log.Printf("リクエスト URL:%v\n", result.URL)
    	if len(result.SignedHeaders) > 0 {
    		// 返された結果に署名付きヘッダーが含まれている場合、署名付き URL を使用して GET リクエストを送信するときに、対応するリクエストヘッダーを含める必要があります。そうしないと、リクエストが失敗したり、署名エラーが発生したりする可能性があります。
    		log.Printf("署名付きヘッダー:\n")
    		for k, v := range result.SignedHeaders {
    			log.Printf("%v: %v\n", k, v)
    		}
    	}
    }
    
  2. 他のユーザーは、GET リクエストの署名付き URL を使用してファイルをダウンロードできます。

    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) {
            // HTTP GET リクエストを許可する署名付き URL を指定します。
            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******************************************************";
            // ダウンロードしたオブジェクトを格納するパスを、オブジェクト名と拡張子を含めて指定します。
            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");
    
            // レスポンスコードを指定します。
            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();
            } 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"; // ダウンロードしたオブジェクトの名前を指定します。
    
    fetch(fileURL)
        .then(response => {
            if (!response.ok) {
                throw new Error(`Server replied HTTP code: ${response.status}`);
            }
            return response.blob(); // 応答のタイプを blob に変更します。
        })
        .then(blob => {
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.download=savePath; // ダウンロードしたオブジェクトの名前を指定します。
            document.body.appendChild(link); // このステップにより、署名付き URL がドキュメントに存在することが保証されます。
            link.click(); // 署名付き URL をクリックして、オブジェクトのダウンロードをシミュレートします。
            link.remove(); // オブジェクトがダウンロードされた後、署名付き URL を削除します。
            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"; // ダウンロードしたオブジェクトを保存するパスを指定します。
            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 {
            // 署名付き URL とオブジェクトを保存するパスを指定します。
            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"; // your_username をユーザー名に置き換えます。
            
            // URL オブジェクトを作成します。
            NSURL *url = [NSURL URLWithString:fileURL];
            
            // オブジェクトダウンロードタスクを作成します。
            NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                // エラーを処理します。
                if (error) {
                    NSLog(@"Error during download: %@", error.localizedDescription);
                    return;
                }
                
                // オブジェクト内のデータを確認します。
                if (!data) {
                    NSLog(@"No data received.");
                    return;
                }
                
                // オブジェクトを保存します。
                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);
                }
            }];
            
            // オブジェクトダウンロードタスクを開始します。
            [task resume];
            
            // メインスレッドを実行し続けて、非同期リクエストを完了します。
            [[NSRunLoop currentRunLoop] run];
        }
        return 0;
    }

一般的なシナリオ

オブジェクトの特定のバージョンに対する HTTP GET リクエストを許可する署名付き URL を生成する

次のサンプルコードは、オブジェクトの特定のバージョンに対する HTTP GET リクエストを許可する署名付き URL を生成する方法を示しています。

package main

import (
	"context"
	"flag"
	"log"
	"time"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// グローバル変数を定義します。
var (
	region     string // バケットが配置されているリージョン。
	bucketName string // バケットの名前。
	objectName string // オブジェクトの名前。
)

// init 関数は、コマンドラインパラメーターを初期化するために使用されます。
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// リージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// デフォルトの構成をロードし、資格情報プロバイダーとリージョンを指定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSS クライアントを作成します。
	client := oss.NewClient(cfg)

	// GetObject リクエストの署名付き URL を生成します。
	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
		Bucket:    oss.Ptr(bucketName),
		Key:       oss.Ptr(objectName),
		VersionId: oss.Ptr("yourVersionId"), // バージョン ID を指定します。
	},
		oss.PresignExpires(10*time.Minute),
	)
	if err != nil {
		log.Fatalf("failed to get object presign %v", err)
	}
	log.Printf("get object presign result: %#v\n", result)
	log.Printf("get object url: %#v\n", result.URL)
}

特定のリクエストヘッダーを含む署名付き URL を使用してオブジェクトをダウンロードする

署名付き URL を生成するときにリクエストヘッダーを指定する場合、署名付き URL を使用する GET リクエストに同じリクエストヘッダーを含める必要があります。これは、リクエストの失敗や署名エラーを防ぐために必要です。

  1. 特定のリクエストヘッダーを含み、HTTP GET リクエストを許可する署名付き URL を生成します。

    package main
    
    import (
    	"context"
    	"flag"
    	"log"
    
    	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
    	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
    )
    
    // グローバル変数を定義します。
    var (
    	region     string // バケットが配置されているリージョン。
    	bucketName string // バケットの名前。
    	objectName string // オブジェクトの名前。
    )
    
    // init 関数は、コマンドラインパラメーターを初期化するために使用されます。
    func init() {
    	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
    	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
    	flag.StringVar(&objectName, "object", "", "The name of the object.")
    }
    
    func main() {
    	// コマンドラインパラメーターを解析します。
    	flag.Parse()
    
    	// バケット名が空かどうかを確認します。
    	if len(bucketName) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, bucket name required")
    	}
    
    	// リージョンが空かどうかを確認します。
    	if len(region) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, region required")
    	}
    
    	// オブジェクト名が空かどうかを確認します。
    	if len(objectName) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, object name required")
    	}
    
    	// デフォルトの構成をロードし、資格情報プロバイダーとリージョンを指定します。
    	cfg := oss.LoadDefaultConfig().
    		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
    		WithRegion(region)
    
    	// OSS クライアントを作成します。
    	client := oss.NewClient(cfg)
    
    	// GetObject リクエストの署名付き URL を生成します。
    	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
    		Bucket:                     oss.Ptr(bucketName),
    		Key:                        oss.Ptr(objectName),
    		RangeBehavior:              oss.Ptr("standard"),
    		RequestPayer:               oss.Ptr("requestpayer"),
    	},
    	)
    	if err != nil {
    		log.Fatalf("failed to get object presign %v", err)
    	}
    
    	log.Printf("リクエストメソッド:%v\n", result.Method)
    	log.Printf("リクエストの有効期限:%v\n", result.Expiration)
    	log.Printf("リクエスト URL:%v\n", result.URL)
    	if len(result.SignedHeaders) > 0 {
    		// 返された結果に署名付きヘッダーが含まれている場合、署名付き URL を使用して GET リクエストを送信するときに、対応するリクエストヘッダーを指定する必要があります。
    		log.Printf("署名付きヘッダー:\n")
    		for k, v := range result.SignedHeaders {
    			log.Printf("%v: %v\n", k, v)
    		}
    	}
    }
    
  2. 署名付き URL を使用し、リクエストで同じリクエストヘッダーを指定してオブジェクトをダウンロードします。

    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 "x-oss-range-behavior: standard" \
    -H "x-oss-request-payer: requester" \
    -o "myfile.txt"
    package main
    
    import (
    	"io"
    	"log"
    	"net/http"
    	"os"
    )
    
    func main() {
    	// 生成された署名付き URL を指定します。
    	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******************************************************"
    
    	// 生成された署名付き URL を使用して HTTP GET メソッドでファイルをダウンロードします。
    	req, err := http.NewRequest(http.MethodGet, url, nil)
    	if err != nil {
    		log.Fatalf("Failed to create PUT request: %v", err)
    	}
    
    	// リクエストヘッダーを設定します。
    	req.Header.Set("X-Oss-Range-Behavior", "standard")
    	req.Header.Set("X-Oss-Request-Payer", "requester")
    
    	// リクエストを開始します。
    	client := &http.Client{}
    	resp, err := client.Do(req)
    	if err != nil {
    		log.Fatalf("Failed to upload file: %v", err)
    	}
    	defer resp.Body.Close()
    
    	// ファイルが書き込まれるローカルパスを定義します。
    	filePath := "C:/downloads/myfile.txt"
    
    	// ローカルファイルを作成または開きます。
    	file, err := os.Create(filePath)
    	if err != nil {
    		log.Fatalf("failed to create or open file: %v", err)
    	}
    	defer file.Close() // 関数が完了したときにファイルが閉じられることを確認します。
    
    	// io.Copy を使用してファイルの内容をローカルファイルに書き込みます。
    	n, err := io.Copy(file, resp.Body)
    	if err != nil {
    		log.Fatalf("failed to read object %v", err)
    	}
    
    	// レスポンスボディを閉じます。
    	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)
    }
    

署名付き URL を使用してオブジェクトのダウンロードを強制する

  1. response-content-disposition パラメーターを使用して署名付き URL を生成します。

    package main
    
    import (
    	"context"
    	"flag"
    	"log"
    
    	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
    	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
    )
    
    // グローバル変数を定義します。
    var (
    	region     string // バケットが配置されているリージョン。
    	bucketName string // バケットの名前。
    	objectName string // オブジェクトの名前。
    )
    
    // init 関数は、コマンドラインパラメーターを初期化するために使用されます。
    func init() {
    	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
    	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
    	flag.StringVar(&objectName, "object", "", "The name of the object.")
    }
    
    func main() {
    	// コマンドラインパラメーターを解析します。
    	flag.Parse()
    
    	// バケット名が空かどうかを確認します。
    	if len(bucketName) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, bucket name required")
    	}
    
    	// リージョンが空かどうかを確認します。
    	if len(region) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, region required")
    	}
    
    	// オブジェクト名が空かどうかを確認します。
    	if len(objectName) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, object name required")
    	}
    
    	// デフォルトの構成をロードし、資格情報プロバイダーとリージョンを指定します。
    	cfg := oss.LoadDefaultConfig().
    		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
    		WithRegion(region)
    
    	// OSS クライアントを作成します。
    	client := oss.NewClient(cfg)
    
    	// GetObject リクエストの署名付き URL を生成します。
    	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
    		Bucket:                     oss.Ptr(bucketName),
    		Key:                        oss.Ptr(objectName),
    		ResponseContentDisposition: oss.Ptr("attachment;filename=test.txt"),
    	},
    	)
    	if err != nil {
    		log.Fatalf("failed to get object presign %v", err)
    	}
    
    	log.Printf("リクエストメソッド:%v\n", result.Method)
    	log.Printf("リクエストの有効期限:%v\n", result.Expiration)
    	log.Printf("リクエスト URL:%v\n", result.URL)
    	if len(result.SignedHeaders) > 0 {
    		// 返された結果に署名付きヘッダーが含まれている場合、署名付き URL を使用して GET リクエストを送信するときに、対応するリクエストヘッダーを指定する必要があります。
    		log.Printf("署名付きヘッダー:\n")
    		for k, v := range result.SignedHeaders {
    			log.Printf("%v: %v\n", k, v)
    		}
    	}
    }
    

  2. クエリパラメーター付きの署名付き URL を使用してファイルを直接ダウンロードします。

    curl -X GET "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?response-content-disposition=attachment%3B%20filename%3Dtest.txt&x-oss-date=20241113T093321Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************&x-oss-signature=ed5a******************************************************" \
    -o "myfile.txt"
    package main
    
    import (
    	"io"
    	"log"
    	"net/http"
    	"os"
    )
    
    func main() {
    	// 生成された署名付き URL を指定します。
    	url := "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?response-content-disposition=attachment%3B%20filename%3Dtest.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******************************************************"
    
    	// 生成された署名付き URL を使用して HTTP GET メソッドでファイルをダウンロードします。
    	req, err := http.NewRequest(http.MethodGet, url, nil)
    	if err != nil {
    		log.Fatalf("Failed to create PUT request: %v", err)
    	}
    
    	// リクエストを開始します。
    	client := &http.Client{}
    	resp, err := client.Do(req)
    	if err != nil {
    		log.Fatalf("Failed to upload file: %v", err)
    	}
    	defer resp.Body.Close()
    
    	// ファイルが書き込まれるローカルパスを定義します。
    	filePath := "C:/downloads/myfile.txt"
    
    	// ローカルファイルを作成または開きます。
    	file, err := os.Create(filePath)
    	if err != nil {
    		log.Fatalf("failed to create or open file: %v", err)
    	}
    	defer file.Close() // 関数が完了したときにファイルが閉じられることを確認します。
    
    	// io.Copy を使用してファイルの内容をローカルファイルに書き込みます。
    	n, err := io.Copy(file, resp.Body)
    	if err != nil {
    		log.Fatalf("failed to read object %v", err)
    	}
    
    	// レスポンスボディを閉じます。
    	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)
    }
    

カスタムドメイン名を使用して署名付き URL を生成する

次のサンプルコードは、カスタムドメイン名を使用して署名付き URL を生成する方法を示しています。

package main

import (
	"context"
	"flag"
	"log"
	"time"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// グローバル変数を定義します。
var (
	region     string // バケットが配置されているリージョン。
	bucketName string // バケットの名前。
	objectName string // オブジェクトの名前。
)

// init 関数は、コマンドラインパラメーターを初期化するために使用されます。
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// リージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// デフォルトの構成をロードし、資格情報プロバイダーとリージョンを指定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region).
		WithEndpoint("http://static.example.com").
		WithUseCName(true)

	// OSS クライアントを作成します。
	client := oss.NewClient(cfg)

	// GetObject リクエストの署名付き URL を生成します。
	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
		//RequestPayer: oss.Ptr("requester"), // リクエスタの ID を指定します。
	},
		oss.PresignExpires(10*time.Minute),
	)
	if err != nil {
		log.Fatalf("failed to get object presign %v", err)
	}

	log.Printf("リクエストメソッド:%v\n", result.Method)
	log.Printf("リクエストの有効期限:%v\n", result.Expiration)
	log.Printf("リクエスト URL:%v\n", result.URL)
	if len(result.SignedHeaders) > 0 {
		// HTTP GET リクエストを許可する署名付き URL を生成するときにリクエストヘッダーを指定する場合は、署名付き URL を使用して開始された GET リクエストにリクエストヘッダーが含まれていることを確認してください。これにより、リクエストの失敗や署名エラーを防ぐことができます。
		log.Printf("署名付きヘッダー:\n")
		for k, v := range result.SignedHeaders {
			log.Printf("%v: %v\n", k, v)
		}
	}
}

リファレンス

  • 署名付き URL を使用してオブジェクトをダウンロードするために使用される完全なサンプルコードについては、「GitHub の例」をご参照ください。

  • 署名付き URL を使用してオブジェクトをダウンロードするために呼び出すことができる API 操作の詳細については、「Presign」をご参照ください。