Todos os produtos
Search
Central de documentação

Object Storage Service:Upload por anexação (Go SDK V2)

Última atualização: Jul 03, 2026

O upload por anexação permite adicionar conteúdo diretamente ao final de um objeto anexável existente. Este tópico descreve como executar um upload por anexação com o OSS SDK for Go.

Observações de uso

  • Os códigos de exemplo neste tópico usam o ID da região cn-hangzhou para a região China (Hangzhou). Por padrão, o endpoint público acessa recursos em um bucket. Para acessar recursos do bucket com outros serviços da Alibaba Cloud na mesma região, use o endpoint interno. Para mais informações sobre regiões e endpoints do OSS, consulte Regiões e endpoints.

  • Neste tópico, as credenciais de acesso são lidas de variáveis de ambiente. Para saber como configurar credenciais de acesso, consulte Configurar credenciais de acesso.

  • Se o arquivo de destino não existir, a chamada à API de upload por anexação criará um objeto anexável.

  • Caso o arquivo de destino já exista:

    • Se o arquivo for um objeto anexável e a posição de anexação especificada coincidir com o tamanho atual do arquivo, o conteúdo será adicionado ao final dele.

    • Se o arquivo for um objeto anexável, mas a posição de anexação especificada diferir do tamanho atual do arquivo, o sistema lançará a exceção PositionNotEqualToLength.

    • Se o arquivo não for um objeto anexável, como um objeto normal enviado via upload simples, o sistema acionará a exceção ObjectNotAppendable.

Permissões

Por padrão, uma conta Alibaba Cloud tem permissões completas. Usuários RAM ou funções RAM vinculados a essa conta não têm permissão inicialmente. A conta Alibaba Cloud ou o administrador deve conceder as permissões operacionais necessárias por meio de políticas do RAM ou Bucket Policy.

API

Ação

Descrição

AppendObject

oss:PutObject

Envia um objeto anexando-o a um objeto existente.

oss:PutObjectTagging

Necessária quando tags de objeto são especificadas via x-oss-tagging durante o envio por anexação.

Definição de métodos

Para cenários de upload por anexação, o OSS SDK for Go oferece a operação AppendFile, que simula comportamentos de leitura e escrita de arquivos para objetos em um bucket. A tabela a seguir detalha as operações AppendFile e AppendObject.

Nome da operação

Descrição

Client.AppendObject

Executa um upload por anexação. O objeto final pode ter até 5 GiB.

Suporta verificação de integridade de dados CRC-64 (ativada por padrão).

Compatível com barras de progresso.

O corpo da requisição é do tipo io.Reader. Se o tipo io.Seeker for suportado, haverá retransmissão em caso de falha. Esta operação não é idempotente e a retransmissão pode falhar.

Client.AppendFile

Oferece as mesmas capacidades da operação Client.AppendObject.

Otimiza a tolerância a falhas de retransmissão.

Inclui a operação AppendOnlyFile.

AppendOnlyFile.Write

AppendOnlyFile.WriteFrom

API premium de upload por anexação: AppendFile

A operação AppendFile envia dados por anexação. Se o objeto não existir, o sistema criará um objeto anexável. Caso o objeto exista mas não seja anexável, um erro será retornado.

O código de exemplo abaixo ilustra como definir a operação AppendFile.

type AppendOnlyFile struct {
...
}

func (c *Client) AppendFile(ctx context.Context, bucket string, key string, optFns ...func(*AppendOptions)) (*AppendOnlyFile, error)

Parâmetros da requisição

Parâmetro

Tipo

Descrição

ctx

context.Context

O contexto da requisição.

bucket

string

O nome do bucket.

key

string

O nome do objeto.

optFns

...func(*AppendOptions)

Opcional. As opções de configuração para anexar um arquivo.

A tabela a seguir descreve os parâmetros de AppendOptions.

Parâmetro

Tipo

Descrição

RequestPayer

*string

Se o modo de pagamento pelo solicitante estiver ativado, defina este parâmetro como 'requester'.

CreateParameter

*AppendObjectRequest

Define os metadados de um objeto durante o primeiro envio. Os metadados incluem ContentType, Metadata, permissões e classe de armazenamento. Para mais informações, consulte AppendObjectRequest.

Valores de retorno

Valor de retorno

Tipo

Descrição

file

*AppendOnlyFile

A instância do arquivo anexável. Este parâmetro é válido apenas quando err é nil. Para mais informações, consulte AppendOnlyFile.

err

error

O status da abertura do arquivo anexável. Se a operação falhar, err não será nil.

A tabela seguinte detalha a operação AppendOnlyFile.

Nome da operação

Descrição

Close() error

Fecha o identificador de arquivo para liberar recursos.

Write(b []byte) (int, error)

Escreve os dados em b no fluxo de dados e retorna o número de bytes gravados e qualquer erro encontrado.

WriteFrom(r io.Reader) (int64, error)

Escreve os dados em r no fluxo de dados e retorna o número de bytes gravados e qualquer erro encontrado.

Stat() (os.FileInfo, error)

Obtém as informações do objeto, incluindo tamanho, hora da última modificação e metadados.

API básica de upload por anexação: AppendObject

func (c *Client) AppendObject(ctx context.Context, request *AppendObjectRequest, optFns ...func(*Options)) (*AppendObjectResult, error)

Parâmetros da requisição

Parâmetro

Tipo

Descrição

ctx

context.Context

O contexto da requisição, usado para definir o tempo limite total da requisição.

request

*AppendObjectRequest

Os parâmetros da requisição para uma operação de API específica. Para mais informações, consulte AppendObjectRequest.

optFns

...func(*Options)

Opcional. Os parâmetros de configuração no nível da operação. Para mais informações, consulte Options.

Valores de retorno

Valor de retorno

Tipo

Descrição

result

*AppendObjectResult

O valor de retorno da operação de API. Este parâmetro é válido apenas quando err é nil. Para mais informações, consulte AppendObjectResult.

err

error

O status da requisição. Se a requisição falhar, err não será nil.

Códigos de exemplo

Usar AppendFile para executar um upload por anexação

package main

import (
	"context"
	"flag"
	"log"
	"os"

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

// Define global variables.
var (
	region     string // The storage region.
	bucketName string // The bucket name.
	objectName string // The object name.
)

// The init function is used to initialize command-line parameters.
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() {
	// 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 storage 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")
	}

	// Configure the OSS client.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// Create an OSS client.
	client := oss.NewClient(cfg)

	// Create an instance of an appendable file.
	f, err := client.AppendFile(context.TODO(),
		bucketName,
		objectName,
		func(ao *oss.AppendOptions) {
			ao.CreateParameter = &oss.AppendObjectRequest{
				Acl: oss.ObjectACLPrivate, // Set the access permissions of the object to private.
				Metadata: map[string]string{
					"user": "jack", // Set the metadata of the object.
				},
				Tagging: oss.Ptr("key=value"), // Set the tags for the object.
			}
		})

	if err != nil {
		log.Fatalf("failed to append file %v", err)
	}
	defer f.Close() // Make sure that the data stream is closed when the function ends.

	// Open the local file example1.txt.
	lf, err := os.Open("/local/dir/example1.txt")
	if err != nil {
		log.Fatalf("failed to open local file %v", err)
	}

	// Append the content of example1.txt to the OSS object.
	_, err = f.WriteFrom(lf)
	if err != nil {
		log.Fatalf("failed to append file %v", err)
	}
	lf.Close() // Close the local file.

	// Open the local file example2.txt.
	lf, err = os.Open("/local/dir/example2.txt")
	if err != nil {
		log.Fatalf("failed to open local file %v", err)
	}

	// Append the content of example2.txt to the OSS object.
	_, err = f.WriteFrom(lf)
	if err != nil {
		log.Fatalf("failed to append file %v", err)
	}
	lf.Close() // Close the local file.

	// Read the content of the local file example3.txt.
	lb, err := os.ReadFile("/local/dir/example3.txt")
	if err != nil {
		log.Fatalf("failed to read local file %v", err)
	}

	// Append the content of example3.txt to the OSS object.
	_, err = f.Write(lb)
	if err != nil {
		log.Fatalf("failed to append file %v", err)
	}

	// Print the log information about the successful append upload.
	log.Printf("append file successfully")
}

Usar AppendObject para executar um upload por anexação

package main

import (
	"context"
	"flag"
	"log"
	"strings"

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

// Define global variables.
var (
	region     string
	bucketName string
	objectName string
)

// The init function is used to initialize command-line parameters.
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() {
	// Parse command-line parameters.
	flag.Parse()

	// Define the initial position for the append upload.
	var (
		position = int64(0)
	)

	// 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")
	}

	// Load the default configurations and set the credential provider and region.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// Create an OSS client.
	client := oss.NewClient(cfg)

	// Define the content to append.
	content := "hi append object"

	// Create an AppendObject request.
	request := &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(position),
		Body:     strings.NewReader(content),
	}

	// Execute the AppendObject request and process the result.
	// The position for the first append upload is 0. The return value contains the position for the next append upload.
	result, err := client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to append object %v", err)
	}

	// Create the second AppendObject request.
	request = &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(result.NextPosition), // Obtain NextPosition from the return value of the first AppendObject request.
		Body:     strings.NewReader("hi append object"),
	}

	// Execute the second AppendObject request and process the result.
	result, err = client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to append object %v", err)
	}

	log.Printf("append object result:%#v\n", result)
}

Cenários comuns

Executar um upload por anexação e exibir uma barra de progresso

package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"strings"

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

// Define global variables.
var (
	region     string
	bucketName string
	objectName string
)

// The init function is used to initialize command-line parameters.
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() {
	// Parse command-line parameters.
	flag.Parse()

	// Define the initial position for the append upload.
	var (
		position = int64(0)
	)

	// 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")
	}

	// Load the default configurations and set the credential provider and region.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// Create an OSS client.
	client := oss.NewClient(cfg)

	// Define the content to append.
	content := "hi append object"

	// Create an AppendObject request.
	request := &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(position),
		Body:     strings.NewReader(content),
		ProgressFn: func(increment, transferred, total int64) {
			fmt.Printf("increment:%v, transferred:%v, total:%v\n", increment, transferred, total)
		}, // The progress callback function, which is used to display the upload progress.
	}

	// Execute the first AppendObject request and process the result.
	// The position for the first append upload is 0. The return value contains the position for the next append upload.
	result, err := client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to append object %v", err)
	}

	// Create the second AppendObject request.
	request = &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(result.NextPosition), // Obtain NextPosition from the return value of the first AppendObject request.
		Body:     strings.NewReader("hi append object"),
		ProgressFn: func(increment, transferred, total int64) {
			fmt.Printf("increment:%v, transferred:%v, total:%v\n", increment, transferred, total)
		}, // The progress callback function, which is used to display the upload progress.
	}

	// Execute the second AppendObject request and process the result.
	result, err = client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to append object %v", err)
	}

	// Print the versionId of the appended object.
	log.Printf("append object result:%#v\n", *result.VersionId)
}

Referências

  • Para obter o código de exemplo completo sobre upload por anexação, consulte os exemplos no GitHub e o Guia do Desenvolvedor.

  • Para mais detalhes sobre a operação de API premium de upload por anexação, consulte AppendFile.

  • Para mais informações sobre a operação de API básica de upload por anexação, consulte AppendObject.