Unggah multi-bagian membagi objek besar menjadi beberapa bagian dan mengunggahnya secara independen. Setelah semua bagian diunggah, panggil CompleteMultipartUpload untuk menyusunnya menjadi satu objek utuh.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Bucket OSS
Izin
oss:PutObject. Untuk detailnya, lihat Lampirkan kebijakan kustom ke RAM userKredensial akses yang dikonfigurasi sebagai variabel lingkungan. Untuk detailnya, lihat Konfigurasikan kredensial akses
Cara kerja
Unggah multi-bagian terdiri dari tiga langkah:
Initiate — Panggil
Client.InitiateMultipartUploaduntuk mendapatkan ID unggah unik dari OSS.Upload parts — Panggil
Client.UploadPartuntuk mengunggah setiap bagian menggunakan ID unggah tersebut.Complete — Panggil
Client.CompleteMultipartUploaduntuk menyusun semua bagian yang telah diunggah menjadi objek akhir.
Perilaku penomoran bagian:
Nomor bagian menentukan urutan bagian dalam objek akhir. Mengunggah bagian baru dengan nomor bagian yang sudah ada akan menimpa bagian aslinya.
OSS mengembalikan hash MD5 dari setiap bagian yang diunggah dalam header respons
ETag, lalu memvalidasinya terhadap hash yang dihitung oleh OSS SDK for Go. Jika berbeda, OSS mengembalikanInvalidDigest. Untuk informasi lebih lanjut, lihat Dapatkah saya menggunakan nilai ETag sebagai hash MD5 OSS untuk memeriksa konsistensi data.
Kode contoh menggunakan wilayah cn-hangzhou dan titik akhir publik. Untuk mengakses OSS dari layanan Alibaba Cloud lain di wilayah yang sama, alihkan ke titik akhir internal. Untuk daftar wilayah dan titik akhir yang tersedia, lihat Wilayah dan titik akhir.Unggah file lokal
Contoh berikut membaca file lokal ke memori, membaginya menjadi 3 bagian, mengunggah bagian-bagian tersebut secara konkuren menggunakan goroutine, lalu menyusunnya.
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"
)
var (
region string
bucketName string
objectName string
)
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() {
flag.Parse()
var uploadId string
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)
// Initiate the multipart upload and get an upload ID.
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)
}
log.Printf("upload ID: %s\n", *initResult.UploadId)
uploadId = *initResult.UploadId
var wg sync.WaitGroup
var parts []oss.UploadPart
var mu sync.Mutex
count := 3
// Read the local file into memory. Replace "yourLocalFile" with the actual file path.
file, err := os.Open("yourLocalFile")
if err != nil {
log.Fatalf("failed to open file: %v", err)
}
defer file.Close()
bufReader := bufio.NewReader(file)
content, err := io.ReadAll(bufReader)
if err != nil {
log.Fatalf("failed to read file: %v", err)
}
log.Printf("file size: %d bytes\n", len(content))
// Split the file into parts and upload them concurrently.
chunkSize := len(content) / count
if chunkSize == 0 {
chunkSize = 1
}
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()
partRequest := &oss.UploadPartRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
PartNumber: int32(partNumber),
UploadId: oss.Ptr(uploadId),
Body: bytes.NewReader(content[start:end]),
}
partResult, err := client.UploadPart(context.TODO(), partRequest)
if err != nil {
log.Fatalf("failed to upload part %d: %v", partNumber, err)
}
mu.Lock()
parts = append(parts, oss.UploadPart{
PartNumber: partRequest.PartNumber,
ETag: partResult.ETag,
})
mu.Unlock()
}(i+1, start, end)
}
wg.Wait()
// Assemble all uploaded parts into the final object.
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)
}
log.Printf("multipart upload complete: %#v\n", result)
}Contoh lainnya
Referensi API
Operasi | Description |
Memulai tugas unggah multi-bagian dan mengembalikan ID unggah | |
Mengunggah satu bagian | |
Menyusun bagian yang diunggah menjadi objek utuh | |
Membatalkan tugas unggah multi-bagian | |
Mendaftar bagian yang diunggah dalam tugas tertentu | |
Mendaftar semua tugas unggah multi-bagian yang sedang berlangsung di dalam bucket. Tugas yang sedang berlangsung adalah tugas yang telah dimulai tetapi belum diselesaikan atau dibatalkan. |
Untuk kode contoh lengkap, lihat GitHub.