フォームアップロードを使用すると、webアプリケーションの標準HTMLフォームを使用して、オブジェクトをObject Storage Service (OSS) に直接アップロードできます。 このトピックでは、OSS SDK for Go 2.0を使用して署名やアップロードポリシーなどの情報を生成し、HTTP Postメソッドを使用してオブジェクトをOSSにアップロードする方法について説明します。
使用上の注意
このトピックのサンプルコードでは、中国 (杭州) リージョンのリージョンID
cn-hangzhou
を使用しています。 デフォルトでは、パブリックエンドポイントはバケット内のリソースにアクセスするために使用されます。 バケットが配置されているのと同じリージョンにある他のAlibaba Cloudサービスを使用してバケット内のリソースにアクセスする場合は、内部エンドポイントを使用します。 OSSリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。このトピックでは、アクセス資格情報は環境変数から取得します。 アクセス資格情報の設定方法の詳細については、「アクセス資格情報の設定」をご参照ください。
フォームアップロードを使用してアップロードするオブジェクトのサイズは、5 GBを超えることはできません。
例
次のサンプルコードでは、フォームのアップロードを実行する方法の例を示します。 フォームアップロードの完全なプロセスは、次の手順で構成されます。
アップロードポリシーの作成: バケット名、署名バージョン、資格情報、リクエスト日、リクエスト本文の長さ範囲など、アップロードリクエストの有効期間と条件を指定します。
アップロードポリシーの処理: アップロードポリシーをJSON文字列に変換し、文字列をBase64-encodeします。
署名キーの生成: HMAC-SHA256アルゴリズムを使用して、日付、リージョン、サービス、およびリクエストタイプを含む署名キーを生成します。
署名の計算: 生成された署名キーを使用して、Base64でエンコードされたポリシー文字列に署名し、署名を16進文字列に変換します。
リクエスト本文の作成: マルチパートフォームライターを作成し、フォームにオブジェクトキー、ポリシー、署名バージョン、資格情報、リクエスト日、署名を指定して、フォームにアップロードするデータを書き込みます。
リクエストの作成と実行: HTTP POSTリクエストを作成し、リクエストヘッダーを指定します。 リクエストを送信し、応答ステータスコードを確認して、リクエストが成功したことを確認します。
package main
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"hash"
"io"
"log"
"mime/multipart"
"net/http"
"time"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
var (
region string // The region in which the bucket is located.
bucketName string // The name of the bucket.
objectName string // The name of the object.
product = "oss"
)
// Specify the init function used to initialize command line parameters.
func init() {
flag.StringVar(®ion, "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() {
// Parse command line parameters.
flag.Parse()
// Check whether the bucket name is empty.
if len(bucketName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, bucket name required")
}
// Check whether the region is empty.
if len(region) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, region required")
}
// Check whether the object name is empty.
if len(objectName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, object name required")
}
// Create a credential provider.
credentialsProvider := credentials.NewEnvironmentVariableCredentialsProvider()
cred, err := credentialsProvider.GetCredentials(context.TODO())
if err != nil {
log.Fatalf("GetCredentials fail, err:%v", err)
}
// Specify the content that you want to upload.
content := "hi oss"
// Create an upload policy.
utcTime := time.Now().UTC()
date := utcTime.Format("20060102")
expiration := utcTime.Add(1 * time.Hour)
policyMap := map[string]any{
"expiration": expiration.Format("2006-01-02T15:04:05.000Z"),
"conditions": []any{
map[string]string{"bucket": bucketName},
map[string]string{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
map[string]string{"x-oss-credential": fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request",
cred.AccessKeyID, date, region, product)}, // Specify the credentials.
map[string]string{"x-oss-date": utcTime.Format("20060102T150405Z")},
// Specify other conditions.
[]any{"content-length-range", 1, 1024},
// []any{"eq", "$success_action_status", "201"},
// []any{"starts-with", "$key", "user/eric/"},
// []any{"in", "$content-type", []string{"image/jpg", "image/png"}},
// []any{"not-in", "$cache-control", []string{"no-cache"}},
},
}
// Convert the upload policy to a JSON string.
policy, err := json.Marshal(policyMap)
if err != nil {
log.Fatalf("json.Marshal fail, err:%v", err)
}
// Base64-encode the JSON string.
stringToSign := base64.StdEncoding.EncodeToString([]byte(policy))
// Generate a signing key.
hmacHash := func() hash.Hash { return sha256.New() }
signingKey := "aliyun_v4" + cred.AccessKeySecret
h1 := hmac.New(hmacHash, []byte(signingKey))
io.WriteString(h1, date)
h1Key := h1.Sum(nil)
h2 := hmac.New(hmacHash, h1Key)
io.WriteString(h2, region)
h2Key := h2.Sum(nil)
h3 := hmac.New(hmacHash, h2Key)
io.WriteString(h3, product)
h3Key := h3.Sum(nil)
h4 := hmac.New(hmacHash, h3Key)
io.WriteString(h4, "aliyun_v4_request")
h4Key := h4.Sum(nil)
// Calculate the signature.
h := hmac.New(hmacHash, h4Key)
io.WriteString(h, stringToSign)
signature := hex.EncodeToString(h.Sum(nil))
// Build a Post request body.
bodyBuf := &bytes.Buffer{}
// Create a multipart form writer to build the request body.
bodyWriter := multipart.NewWriter(bodyBuf)
// Specify the object information, including the key and metadata.
bodyWriter.WriteField("key", objectName) // Specify the object key (object name).
// bodyWriter.WriteField("x-oss-", value) // Specify the metadata. This parameter is optional.
// Specify the Base64-encoded policy string.
bodyWriter.WriteField("policy", stringToSign)
// Specify the signature version.
bodyWriter.WriteField("x-oss-signature-version", "OSS4-HMAC-SHA256")
// Specify the credentials.
bodyWriter.WriteField("x-oss-credential", fmt.Sprintf("%v/%v/%v/%v/aliyun_v4_request", cred.AccessKeyID, date, region, product))
// Specify the request date.
bodyWriter.WriteField("x-oss-date", utcTime.Format("20060102T150405Z"))
// Specify the signature.
bodyWriter.WriteField("x-oss-signature", signature)
// Create a form field named "file" to upload data.
w, _ := bodyWriter.CreateFormField("file")
// Write the data that you want to upload to the form field.
w.Write([]byte(content))
// Close the form writer and make sure that all data is written to the request body as expected.
bodyWriter.Close()
// Create a Post request.
req, _ := http.NewRequest("POST", fmt.Sprintf("http://%v.oss-%v.aliyuncs.com/", bucketName, region), bodyBuf)
req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
// Execute the Post request.
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatalf("Do fail, err:%v", err)
}
defer resp.Body.Close()
// Check the response status code.
if resp.StatusCode/100 != 2 {
log.Fatalf("Post Object Fail, status code:%v, reason:%v", resp.StatusCode, resp.Status)
}
log.Printf("post object done, status code:%v, request id:%v\n", resp.StatusCode, resp.Header.Get("X-Oss-Request-Id"))
}
関連ドキュメント
フォームアップロードの実行に使用される完全なサンプルコードについては、『GitHub』をご参照ください。