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-hangzhoupour 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 :
-
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.
-
Téléchargez les parties.
Appelez la méthode Client.UploadPart pour télécharger les parties.
RemarquePour 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.
-
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(®ion, "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
Annuler un événement de téléchargement multipartie spécifique
Lister les parties téléchargées avec succès dans un événement de téléchargement multipartie spécifique
Lister les événements de téléchargement multipartie
Téléchargement multipartie avec callbacks
Téléchargement multipartie avec barre de progression
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.