Tous les produits
Search
Centre de documentation

Object Storage Service:Téléchargement multipartie (Go SDK V2)

Dernière mise à jour :Sep 25, 2026

La fonctionnalité de téléchargement multipartie d'Object Storage Service (OSS) vous permet de diviser un objet volumineux en plusieurs parties. Vous pouvez télécharger ces parties séparément. Une fois toutes les parties téléchargées, appelez l'opération CompleteMultipartUpload pour combiner les parties en un objet complet.

Notes

  • L'exemple de code de cette rubrique utilise l'ID de région cn-hangzhou pour la région Chine (Hangzhou) et un endpoint public par défaut. Si vous accédez à OSS depuis d'autres services Alibaba Cloud dans la même région, utilisez un endpoint interne. Pour plus d'informations sur les régions et les endpoints OSS, consultez Régions et endpoints.

  • Les exemples de cette rubrique lisent les identifiants d'accès à partir des variables d'environnement. Pour savoir comment configurer les identifiants d'accès, consultez Configurer les identifiants d'accès.

  • Pour effectuer un téléchargement multipartie, vous devez disposer de l'autorisation oss:PutObject. Pour plus d'informations, consultez Accorder des autorisations personnalisées à un utilisateur RAM.

Processus de téléchargement multipartie

Un téléchargement multipartie comprend les trois étapes suivantes :

  1. Initialisez un événement de téléchargement multipartie.

    Appelez la méthode Client.InitiateMultipartUpload pour obtenir un ID de téléchargement globalement unique auprès d'OSS.

  2. Téléchargez les parties.

    Appelez la méthode Client.UploadPart pour télécharger les parties.

    Remarque
    • Pour un ID de téléchargement donné, le numéro de partie identifie la position de la partie au sein de l'objet. Si vous téléchargez une nouvelle partie avec un numéro de partie existant, OSS écrase la partie existante.

    • OSS inclut le hachage MD5 de la partie reçue dans l'en-tête ETag de la réponse.

    • OSS calcule le hachage MD5 des données téléchargées et le compare au hachage calculé par le kit de développement logiciel (SDK). Si les hachages ne correspondent pas, OSS renvoie un code d'erreur InvalidDigest.

  3. Finalisez le téléchargement multipartie.

    Une fois toutes les parties téléchargées, appelez la méthode Client.CompleteMultipartUpload pour combiner toutes les parties en un objet complet.

Exemple de code

Le code suivant montre comment diviser un fichier local volumineux en plusieurs parties, télécharger les parties simultanément dans un bucket, puis combiner les parties en un objet complet.

package main

import (
	"bufio"
	"bytes"
	"context"
	"flag"
	"io"
	"log"
	"os"
	"sync"

	"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 region where the bucket is located.
	bucketName string // The name of the source bucket.
	objectName string // The name of the source object.

)

// The init function initializes 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 source bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the source object.")
}

func main() {
	// Parse command-line parameters.
	flag.Parse()

	// Define the upload ID.
	var uploadId string

	// Check if the source bucket name is empty.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source bucket name required")
	}

	// Check if the region is empty.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// Check if the source object name is empty.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source object name required")
	}

	// Load 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)

	// Initialize the multipart upload request.
	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}
	initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)
	if err != nil {
		log.Fatalf("failed to initiate multipart upload %v", err)
	}

	// Print the result of the multipart upload initialization.
	log.Printf("initiate multipart upload result:%#v\n", *initResult.UploadId)
	uploadId = *initResult.UploadId

	// Initialize the wait group and mutex.
	var wg sync.WaitGroup
	var parts []oss.UploadPart
	count := 3
	var mu sync.Mutex

	// Read the local file into memory. Replace yourLocalFile with the actual local file name and path.
	file, err := os.Open("yourLocalFile")
	if err != nil {
		log.Fatalf("failed to open local file %v", err)
	}
	defer file.Close()

	bufReader := bufio.NewReader(file)
	content, err := io.ReadAll(bufReader)
	if err != nil {
		log.Fatalf("failed to read local file %v", err)
	}
	log.Printf("file size: %d\n", len(content))

	// Calculate the size of each part.
	chunkSize := len(content) / count
	if chunkSize == 0 {
		chunkSize = 1
	}

	// Start multiple goroutines to upload parts concurrently.
	for i := 0; i < count; i++ {
		start := i * chunkSize
		end := start + chunkSize
		if i == count-1 {
			end = len(content)
		}

		wg.Add(1)
		go func(partNumber int, start, end int) {
			defer wg.Done()

			// Create an upload part request.
			partRequest := &oss.UploadPartRequest{
				Bucket:     oss.Ptr(bucketName),                 // The name of the destination bucket.
				Key:        oss.Ptr(objectName),                 // The name of the destination object.
				PartNumber: int32(partNumber),                   // The part number.
				UploadId:   oss.Ptr(uploadId),                   // The upload ID.
				Body:       bytes.NewReader(content[start:end]), // The content of the part.
			}

			// Send the upload part request.
			partResult, err := client.UploadPart(context.TODO(), partRequest)
			if err != nil {
				log.Fatalf("failed to upload part %d: %v", partNumber, err)
			}

			// Record the result of the part upload.
			part := oss.UploadPart{
				PartNumber: partRequest.PartNumber,
				ETag:       partResult.ETag,
			}

			// Use a mutex to protect shared data.
			mu.Lock()
			parts = append(parts, part)
			mu.Unlock()
		}(i+1, start, end)
	}

	// Wait for all goroutines to complete.
	wg.Wait()

	// Complete the multipart upload request.
	request := &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		UploadId: oss.Ptr(uploadId),
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts,
		},
	}
	result, err := client.CompleteMultipartUpload(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to complete multipart upload %v", err)
	}

	// Print the result of the completed multipart upload.
	log.Printf("complete multipart upload result:%#v\n", result)
}

Scénarios courants

Télécharger une chaîne aléatoire d'une longueur spécifiée à l'aide du téléchargement multipartie

Le code suivant montre comment diviser une chaîne aléatoire de 400 Ko en trois parties, télécharger les parties simultanément dans un bucket, puis combiner les parties en un objet complet.

package main

import (
	"bufio"
	"context"
	"flag"
	"io"
	"log"
	"math/rand"
	"strings"
	"sync"
	"time"

	"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 region where the bucket is located.
	bucketName string                                                                     // The name of the bucket.
	objectName string                                                                     // The name of the object.
	letters    = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") // The character set for generating random strings.
)

// The init function initializes 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 upload ID.
	var uploadId string

	// Check if the bucket name is empty.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// Check if the region is empty.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// Check if the object name is empty.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// Load 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)

	// Create a request to initialize the multipart upload.
	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName), // The name of the bucket.
		Key:    oss.Ptr(objectName), // The name of the object.
	}

	// Initialize the multipart upload and handle the result.
	initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)
	if err != nil {
		log.Fatalf("failed to initiate multipart upload %v", err)
	}

	// Print the result of the multipart upload initialization.
	log.Printf("initiate multipart upload result:%#v\n", initResult)
	uploadId = *initResult.UploadId

	// Initialize the wait group and mutex.
	var wg sync.WaitGroup
	var parts []oss.UploadPart
	count := 3
	body := randBody(400000) // Generate a 400 KB random string.
	reader := strings.NewReader(body)
	bufReader := bufio.NewReader(reader)
	content, _ := io.ReadAll(bufReader)
	partSize := len(body) / count
	var mu sync.Mutex

	// Start multiple goroutines to upload parts concurrently.
	for i := 0; i < count; i++ {
		wg.Add(1)
		go func(partNumber int, partSize int, i int) {
			defer wg.Done()

			// Create an upload part request.
			partRequest := &oss.UploadPartRequest{
				Bucket:     oss.Ptr(bucketName),                                             // The name of the bucket.
				Key:        oss.Ptr(objectName),                                             // The name of the object.
				PartNumber: int32(partNumber),                                               // The part number.
				UploadId:   oss.Ptr(uploadId),                                               // The upload ID.
				Body:       strings.NewReader(string(content[i*partSize : (i+1)*partSize])), // The content of the part.
			}

			// Send the upload part request.
			partResult, err := client.UploadPart(context.TODO(), partRequest)
			if err != nil {
				log.Fatalf("failed to upload part %d: %v", partNumber, err)
			}

			// Record the result of the part upload.
			part := oss.UploadPart{
				PartNumber: partRequest.PartNumber,
				ETag:       partResult.ETag,
			}

			// Use a mutex to protect shared data.
			mu.Lock()
			parts = append(parts, part)
			mu.Unlock()
		}(i+1, partSize, i)
	}

	// Wait for all goroutines to complete.
	wg.Wait()

	// Print a message indicating that the parts were uploaded successfully.
	log.Println("upload part success!")

	// Create a request to complete the multipart upload.
	request := &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		UploadId: oss.Ptr(uploadId),
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts,
		},
	}

	// Complete the multipart upload and handle the result.
	result, err := client.CompleteMultipartUpload(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to complete multipart upload %v", err)
	}
	log.Printf("complete multipart upload result:%#v\n", result)
}

// randBody generates a random string of a specified length.
func randBody(n int) string {
	b := make([]rune, n)
	randMarker := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := range b {
		b[i] = letters[randMarker.Intn(len(letters))]
	}
	return string(b)
}

Annuler un événement de téléchargement multipartie spécifique

Dans les scénarios suivants, vous pouvez utiliser la méthode Client.AbortMultipartUpload pour annuler un événement de téléchargement multipartie.

  1. Erreurs de fichier :

    • Si vous détectez une erreur dans le fichier pendant le téléchargement, telle qu'une corruption ou un code malveillant, vous pouvez annuler le téléchargement pour éviter les menaces potentielles.

  2. Réseau instable :

    • Si la connexion réseau est instable ou interrompue, des parties peuvent être perdues ou endommagées. Vous pouvez annuler le téléchargement et le redémarrer pour garantir l'intégrité et la cohérence des données.

  3. Limites de ressources :

    • Si votre espace de stockage est limité et que le fichier est trop volumineux, vous pouvez annuler le téléchargement pour libérer des ressources de stockage pour des tâches plus importantes.

  4. Opération accidentelle :

    • Si vous démarrez accidentellement un téléchargement inutile ou si vous téléchargez la mauvaise version d'un fichier, vous pouvez annuler l'événement de téléchargement.

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

// Define global variables.
var (
	region     string // The region where the bucket is located.
	bucketName string // The name of the source bucket.
	objectName string // The name of the source object.

)

// The init function initializes 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 source bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the source object.")
}

func main() {
	// Parse command-line parameters.
	flag.Parse()

	// Define the upload ID.
	var uploadId string

	// Check if the source bucket name is empty.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source bucket name required")
	}

	// Check if the region is empty.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// Check if the source object name is empty.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source object name required")
	}

	// Load 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)

	// Initialize the multipart upload request.
	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}

	// Execute the multipart upload initialization request.
	initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)
	if err != nil {
		log.Fatalf("failed to initiate multipart upload %v", err)
	}

	// Print the result of the multipart upload initialization.
	log.Printf("initiate multipart upload result:%#v\n", *initResult.UploadId)
	uploadId = *initResult.UploadId

	// Create an AbortMultipartUploadRequest request.
	request := &oss.AbortMultipartUploadRequest{
		Bucket:   oss.Ptr(bucketName), // The name of the bucket.
		Key:      oss.Ptr(objectName), // The name of the object.
		UploadId: oss.Ptr(uploadId),   // The upload ID.
	}
	// Execute the request and handle the result.
	result, err := client.AbortMultipartUpload(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to abort multipart upload %v", err)
	}
	log.Printf("abort multipart upload result:%#v\n", result)

}

Lister les parties téléchargées avec succès dans un événement de téléchargement multipartie spécifique

Dans les scénarios suivants, vous pouvez utiliser le paginateur Client.NewListPartsPaginator pour lister les parties téléchargées avec succès dans un événement de téléchargement multipartie.

Surveiller la progression du téléchargement :

  1. Téléchargements de fichiers volumineux :

    • Lors du téléchargement d'un fichier très volumineux, vous pouvez lister les parties téléchargées pour vous assurer que le processus se déroule comme prévu et identifier rapidement les problèmes.

  2. Reprise des téléchargements :

    • Si le réseau est instable ou si le téléchargement est interrompu, vous pouvez vérifier les parties téléchargées pour décider s'il faut retélécharger les parties restantes. Cela permet la reprise des téléchargements.

  3. Dépannage :

    • Si une erreur se produit pendant le téléchargement, vous pouvez vérifier les parties téléchargées pour localiser rapidement le problème, par exemple une partie spécifique qui n'a pas pu être téléchargée. Vous pouvez ensuite résoudre le problème.

  4. Gestion des ressources :

    • Pour les scénarios nécessitant un contrôle strict des ressources, vous pouvez surveiller la progression du téléchargement pour mieux gérer l'espace de stockage et la bande passante, et garantir une utilisation efficace des ressources.

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

// Define global variables.
var (
	region     string // The region where the bucket is located.
	bucketName string // The name of the source bucket.
	objectName string // The name of the source object.

)

// The init function initializes 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 source bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the source object.")
}

func main() {
	// Parse command-line parameters.
	flag.Parse()

	// Define the upload ID.
	var uploadId string

	// Check if the source bucket name is empty.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source bucket name required")
	}

	// Check if the region is empty.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// Check if the source object name is empty.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source object name required")
	}

	// Load 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)

	// Initialize the multipart upload request.
	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}

	// Execute the multipart upload initialization request.
	initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)
	if err != nil {
		log.Fatalf("failed to initiate multipart upload %v", err)
	}

	// Print the result of the multipart upload initialization.
	log.Printf("initiate multipart upload result:%#v\n", *initResult.UploadId)
	uploadId = *initResult.UploadId

	// Create a request to list parts.
	request := &oss.ListPartsRequest{
		Bucket:   oss.Ptr(bucketName), // The name of the bucket.
		Key:      oss.Ptr(objectName), // The name of the object.
		UploadId: oss.Ptr(uploadId),   // The upload ID.
	}

	// Create a paginator.
	p := client.NewListPartsPaginator(request)

	// Initialize the page counter.
	var i int
	log.Println("List Parts:")

	// Traverse each page in the paginator.
	for p.HasNext() {
		i++

		// Get the data of the next page.
		page, err := p.NextPage(context.TODO())
		if err != nil {
			log.Fatalf("failed to get page %v, %v", i, err)
		}

		// Print the information of each part on the page.
		for _, part := range page.Parts {
			log.Printf("Part Number: %v, ETag: %v, Last Modified: %v, Size: %v, HashCRC64: %v\n",
				part.PartNumber,
				oss.ToString(part.ETag),
				oss.ToTime(part.LastModified),
				part.Size,
				oss.ToString(part.HashCRC64))
		}
	}

}

Lister les événements de téléchargement multipartie

Dans les scénarios suivants, vous pouvez utiliser le paginateur Client.NewListMultipartUploadsPaginator pour lister tous les événements de téléchargement multipartie en cours dans un bucket.

Scénarios de surveillance :

  1. Gestion du téléchargement par lots de fichiers :

    • Lorsque vous devez télécharger de nombreux fichiers, vous pouvez utiliser la méthode ListMultipartUploads pour surveiller toutes les activités de téléchargement multipartie en temps réel. Cela garantit que tous les fichiers sont correctement téléchargés.

  2. Détection et récupération des pannes :

    • Si des problèmes réseau ou d'autres pannes surviennent pendant un téléchargement, certaines parties peuvent échouer. En surveillant les événements de téléchargement multipartie en cours, vous pouvez détecter rapidement ces problèmes et prendre des mesures pour reprendre le téléchargement.

  3. Optimisation et gestion des ressources :

    • Lors de téléchargements de fichiers à grande échelle, la surveillance des événements de téléchargement multipartie en cours aide à optimiser l'allocation des ressources. Par exemple, vous pouvez ajuster l'utilisation de la bande passante ou optimiser la politique de téléchargement en fonction de la progression du téléchargement.

  4. Migration de données :

    • Lors de l'exécution d'un projet de migration de données à grande échelle, vous pouvez surveiller tous les événements de téléchargement multipartie en cours pour vous assurer que la tâche de migration se déroule sans heurt et identifier et résoudre rapidement tout problème potentiel.

Paramètres

Paramètre

Description

Delimiter

Caractère utilisé pour regrouper les noms d'objets. Tous les objets ayant le même préfixe jusqu'à la première occurrence du délimiteur sont regroupés en un seul élément.

MaxUploads

Nombre maximal d'événements de téléchargement multipartie à renvoyer. La valeur par défaut et maximale est 1000.

KeyMarker

Spécifie le point de départ de la liste. La liste inclut les événements de téléchargement multipartie pour les objets dont les noms sont lexicographiquement supérieurs à la valeur KeyMarker. Utilisez ce paramètre avec UploadIDMarker.

Prefix

Filtre la réponse pour inclure uniquement les objets dont les noms commencent par le préfixe spécifié. Notez que les noms d'objets renvoyés contiennent toujours le préfixe.

UploadIDMarker

À utiliser avec KeyMarker pour spécifier le point de départ de la liste.

  • Si KeyMarker n'est pas défini, OSS ignore ce paramètre.

  • Si KeyMarker est défini, la requête renvoie :

    • Les événements de téléchargement multipartie pour les objets dont les noms sont lexicographiquement supérieurs à la valeur KeyMarker.

    • Les événements de téléchargement multipartie pour les objets dont les noms correspondent à la valeur KeyMarker, mais dont les ID de téléchargement sont lexicographiquement supérieurs à la valeur UploadIDMarker.

  • Spécifiez le préfixe file et renvoyez un maximum de 100 résultats

    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"
    )
    
    // Define global variables.
    var (
    	region     string // The region where the bucket is located.
    	bucketName string // The name of the source bucket.
    	objectName string // The name of the source object.
    
    )
    
    // The init function initializes 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 source bucket.")
    	flag.StringVar(&objectName, "object", "", "The name of the source object.")
    }
    
    func main() {
    	// Parse command-line parameters.
    	flag.Parse()
    
    	// Check if the source bucket name is empty.
    	if len(bucketName) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, source bucket name required")
    	}
    
    	// Check if the region is empty.
    	if len(region) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, region required")
    	}
    
    	// Check if the source object name is empty.
    	if len(objectName) == 0 {
    		flag.PrintDefaults()
    		log.Fatalf("invalid parameters, source object name required")
    	}
    
    	// Load 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)
    
    	// Create a request to list multipart uploads.
    	request := &oss.ListMultipartUploadsRequest{
    		Bucket:     oss.Ptr(bucketName), // The name of the bucket.
    		MaxUploads: 100,                 // Specify that a maximum of 100 results are returned.
    		Prefix:     oss.Ptr("file"),     // Specify the prefix as file.
    	}
    
    	// Create a paginator.
    	p := client.NewListMultipartUploadsPaginator(request)
    
    	var i int
    	log.Println("List Multipart Uploads:")
    
    	// Traverse each page in the paginator.
    	for p.HasNext() {
    		i++
    
    		// Get the data of the next page.
    		page, err := p.NextPage(context.TODO())
    		if err != nil {
    			log.Fatalf("failed to get page %v, %v", i, err)
    		}
    
    		// Print the information of each multipart upload on the page.
    		for _, u := range page.Uploads {
    			log.Printf("Upload key: %v, upload id: %v, initiated: %v\n", oss.ToString(u.Key), oss.ToString(u.UploadId), oss.ToTime(u.Initiated))
    		}
    	}
    
    }
    

Téléchargement multipartie avec callbacks

Le code suivant montre comment diviser un fichier de 400 Ko en trois parties, les télécharger simultanément vers Alibaba Cloud OSS, combiner les parties en un objet complet une fois le téléchargement terminé, et déclencher une notification de callback après la combinaison des parties.

package main

import (
	"bufio"
	"context"
	"encoding/base64"
	"encoding/json"
	"flag"
	"io"
	"log"
	"math/rand"
	"strings"
	"sync"
	"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
	letters    = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
)

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)

	client := oss.NewClient(cfg)

	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}
	initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)

	// Define callback parameters.
	callbackMap := map[string]string{
		"callbackUrl":      "https://example.com:23450",                                                                  // Set the URL of the callback server, for example, https://example.com:23450.
		"callbackBody":     "bucket=${bucket}&object=${object}&size=${size}&my_var_1=${x:my_var1}&my_var_2=${x:my_var2}", // Set the callback request body.
		"callbackBodyType": "application/x-www-form-urlencoded",                                                          // Set the callback request body type.
	}

	// Convert the callback parameters to JSON and encode them in Base64 to pass them as callback parameters.
	callbackStr, err := json.Marshal(callbackMap)
	if err != nil {
		log.Fatalf("failed to marshal callback map: %v", err)
	}
	callbackBase64 := base64.StdEncoding.EncodeToString(callbackStr)

	callbackVarMap := map[string]string{}
	callbackVarMap["x:my_var1"] = "this is var 1"
	callbackVarMap["x:my_var2"] = "this is var 2"
	callbackVarStr, err := json.Marshal(callbackVarMap)
	if err != nil {
		log.Fatalf("failed to marshal callback var: %v", err)
	}
	callbackVarBase64 := base64.StdEncoding.EncodeToString(callbackVarStr)

	var wg sync.WaitGroup
	var parts []oss.UploadPart
	count := 3
	body := randBody(400000)
	reader := strings.NewReader(body)
	bufReader := bufio.NewReader(reader)
	content, _ := io.ReadAll(bufReader)
	partSize := len(body) / count
	var mu sync.Mutex
	for i := 0; i < count; i++ {
		wg.Add(1)
		go func(partNumber int, partSize int, i int) {
			defer wg.Done()
			partRequest := &oss.UploadPartRequest{
				Bucket:     oss.Ptr(bucketName),
				Key:        oss.Ptr(objectName),
				PartNumber: int32(partNumber),
				UploadId:   initResult.UploadId,
				Body:       strings.NewReader(string(content[i*partSize : (i+1)*partSize])),
			}
			partResult, err := client.UploadPart(context.TODO(), partRequest)
			if err != nil {
				log.Fatalf("failed to upload part %d: %v", partNumber, err)
			}
			part := oss.UploadPart{
				PartNumber: partRequest.PartNumber,
				ETag:       partResult.ETag,
			}
			mu.Lock()
			parts = append(parts, part)
			mu.Unlock()
		}(i+1, partSize, i)
	}
	wg.Wait()

	request := &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		UploadId: initResult.UploadId,
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts,
		},
		Callback:    oss.Ptr(callbackBase64), // Specify the callback parameters.
		CallbackVar: oss.Ptr(callbackVarBase64),
	}
	result, err := client.CompleteMultipartUpload(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to complete multipart upload %v", err)
	}
	log.Printf("complete multipart upload result:%#v\n", result)
}

func randBody(n int) string {
	b := make([]rune, n)
	randMarker := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := range b {
		b[i] = letters[randMarker.Intn(len(letters))]
	}
	return string(b)
}

Téléchargement multipartie avec barre de progression

package main

import (
	"bufio"
	"bytes"
	"context"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"sync"

	"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 region where the bucket is located.
	bucketName string // The name of the source bucket.
	objectName string // The name of the source object.

)

// The init function initializes 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 source bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the source object.")
}

func main() {
	// Parse command-line parameters.
	flag.Parse()

	// Define the upload ID.
	var uploadId string

	// Check if the source bucket name is empty.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source bucket name required")
	}

	// Check if the region is empty.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// Check if the source object name is empty.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source object name required")
	}

	// Load 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)

	// Initialize the multipart upload request.
	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket:  oss.Ptr(bucketName),
		Key:     oss.Ptr(objectName),
	}

	// Execute the multipart upload initialization request.
	initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)
	if err != nil {
		log.Fatalf("failed to initiate multipart upload %v", err)
	}

	// Print the result of the multipart upload initialization.
	log.Printf("initiate multipart upload result:%#v\n", *initResult.UploadId)
	uploadId = *initResult.UploadId

	// Initialize the wait group and mutex.
	var wg sync.WaitGroup
	var parts []oss.UploadPart
	count := 5
	var mu sync.Mutex

	// Read the local file into memory. Replace /Users/yourLocalPath/yourFileName with the actual path and name of your local file.
	file, err := os.Open("/Users/yourLocalPath/yourFileName")
	if err != nil {
		log.Fatalf("failed to open local file %v", err)
	}
	defer file.Close()

	bufReader := bufio.NewReader(file)
	content, err := io.ReadAll(bufReader)
	if err != nil {
		log.Fatalf("failed to read local file %v", err)
	}
	log.Printf("file size: %d\n", len(content))

	// Calculate the size of each part.
	chunkSize := len(content) / count
	if chunkSize == 0 {
		chunkSize = 1
	}

	// Start multiple goroutines to upload parts concurrently.
	for i := 0; i < count; i++ {
		start := i * chunkSize
		end := start + chunkSize
		if i == count-1 {
			end = len(content)
		}

		wg.Add(1)
		go func(partNumber int, start, end int) {
			defer wg.Done()

			// Create an upload part request.
			partRequest := &oss.UploadPartRequest{
				Bucket:     oss.Ptr(bucketName),                 // The name of the destination bucket.
				Key:        oss.Ptr(objectName),                 // The name of the destination object.
				PartNumber: int32(partNumber),                   // The part number.
				UploadId:   oss.Ptr(uploadId),                   // The upload ID.
				Body:       bytes.NewReader(content[start:end]), // The content of the part.
				ProgressFn: func(increment, transferred, total int64) {
					fmt.Printf("increment:%v, transferred:%v, total:%v\n", increment, transferred, total)
				}, // The progress callback function, used to display the upload progress.
			}

			// Send the upload part request.
			partResult, err := client.UploadPart(context.TODO(), partRequest)
			if err != nil {
				log.Fatalf("failed to upload part %d: %v", partNumber, err)
			}

			log.Printf("successfully uploaded part %d (start: %d, end: %d)", partNumber, start, end)

			// Record the result of the part upload.
			part := oss.UploadPart{
				PartNumber: partRequest.PartNumber,
				ETag:       partResult.ETag,
			}

			// Use a mutex to protect shared data.
			mu.Lock()
			parts = append(parts, part)
			mu.Unlock()
		}(i+1, start, end)
	}

	// Wait for all goroutines to complete.
	wg.Wait()

	// Complete the multipart upload request.
	request := &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		UploadId: oss.Ptr(uploadId),
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts,
		},
	}
	result, err := client.CompleteMultipartUpload(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to complete multipart upload %v", err)
	}

	// Print the versionId of the completed multipart upload.
	log.Printf("complete multipart upload result versionId:%#v\n", result)
}

Références

  • Pour l'exemple de code complet du téléchargement multipartie, consultez l'exemple GitHub.

  • Un téléchargement multipartie complet implique trois opérations API :

    • Pour plus d'informations sur l'opération API permettant d'initialiser un événement de téléchargement multipartie, consultez InitiateMultipartUpload.

    • Pour plus d'informations sur l'opération API permettant de télécharger une partie, consultez UploadPart.

    • Pour plus d'informations sur l'opération API permettant de finaliser un téléchargement multipartie, consultez CompleteMultipartUpload.

  • Pour plus d'informations sur l'opération API permettant d'annuler un événement de téléchargement multipartie, consultez AbortMultipartUpload.

  • Pour plus d'informations sur l'opération API permettant de lister les parties téléchargées, consultez NewListPartsPaginator.

  • Pour plus d'informations sur l'opération API permettant de lister tous les événements de téléchargement multipartie en cours (événements initiés mais non encore finalisés ou annulés), consultez NewListMultipartUploadsPaginator.