La carga mediante formulario permite cargar objetos directamente a Object Storage Service (OSS) con formularios HTML estándar desde aplicaciones web. Este tema describe cómo generar información como una firma y una directiva de carga mediante el SDK de OSS para Go 2.0, y cómo usar el método HTTP Post para cargar un objeto en OSS.
Notas de uso
El código de ejemplo de este tema usa el ID de región
cn-hangzhoucorrespondiente a la región China (Hangzhou). De forma predeterminada, se usa el endpoint público para acceder a los recursos de un bucket. Si desea acceder a los recursos del bucket mediante otros servicios de Alibaba Cloud en la misma región donde se encuentra el bucket, use el endpoint interno. Para obtener más información sobre las regiones y los endpoints de OSS, consulte Regions and endpoints.En este tema, las credenciales de acceso se obtienen de variables de entorno. Para obtener más información sobre cómo configurar las credenciales de acceso, consulte Configure access credentials.
El tamaño del objeto que se carga mediante un formulario no puede superar los 5 GB.
Ejemplos
A continuación se presenta un código de ejemplo que muestra cómo cargar mediante formulario. El proceso completo consta de los siguientes pasos:
**Crear una directiva de carga**: Especifique el periodo de validez y las condiciones de una solicitud de carga, incluido el nombre del bucket, la versión de la firma, las credenciales, la fecha de la solicitud y el rango de longitud del cuerpo de la solicitud.
Procesar la directiva de carga: Convierta la directiva de carga a una cadena JSON y codifíquela en Base64.
Generar una clave de firma: Use el algoritmo HMAC-SHA256 para generar una clave de firma que incluya la fecha, la región, el servicio y el tipo de solicitud.
Calcular una firma: Use la clave de firma generada para firmar la cadena de la directiva codificada en Base64 y convierta la firma a una cadena hexadecimal.
Construir un cuerpo de solicitud: Cree un escritor de formularios multipart, especifique la clave del objeto, la directiva, la versión de la firma, las credenciales, la fecha de la solicitud y la firma en el formulario, y escriba los datos que desea cargar en dicho formulario.
Crear y ejecutar una solicitud: Cree una solicitud HTTP POST y especifique los encabezados de la solicitud. Envíe la solicitud y compruebe el código de estado de la respuesta para asegurarse de que la solicitud se haya completado correctamente.
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"))
}
Referencias
Para consultar el código de ejemplo completo para cargar mediante formulario, visite GitHub.