Object Storage Service (OSS) menyediakan fitur unggah multi-bagian yang memungkinkan Anda mengunggah objek besar dalam beberapa bagian. Setelah semua bagian diunggah, Anda dapat memanggil operasi CompleteMultipartUpload untuk menggabungkannya menjadi satu objek lengkap.
Catatan
Kode contoh dalam topik ini menggunakan ID Wilayah
cn-hangzhoudari Wilayah (Hangzhou) Tiongkok. Secara default, titik akhir publik digunakan untuk mengakses sumber daya dalam bucket. Jika Anda ingin mengakses sumber daya bucket dari layanan Alibaba Cloud lainnya di wilayah yang sama, gunakan titik akhir internal. Untuk informasi lebih lanjut tentang Wilayah dan titik akhir OSS, lihat Wilayah dan titik akhir.Dalam topik ini, kredensial akses diperoleh dari variabel lingkungan. Untuk informasi lebih lanjut tentang cara mengonfigurasi kredensial akses, lihat Konfigurasikan Kredensial Akses.
Untuk menggunakan unggah multi-bagian, Anda harus memiliki izin
oss:PutObject. Untuk informasi lebih lanjut, lihat Lampirkan kebijakan kustom ke Pengguna RAM.
Proses unggah multi-bagian
Unggah multi-bagian melibatkan tiga langkah berikut:
Mulai peristiwa unggah multi-bagian.
Panggil metode Client.InitiateMultipartUpload untuk mendapatkan ID unggah unik secara global yang dibuat oleh OSS.
Unggah bagian-bagian.
Panggil metode Client.UploadPart untuk mengunggah data bagian.
CatatanUntuk ID unggah tertentu, nomor bagian mengidentifikasi posisi sebuah bagian dalam objek lengkap. Jika Anda menggunakan nomor bagian yang sama untuk mengunggah data baru, data bagian yang ada di OSS akan ditimpa.
OSS menyertakan hash MD5 dari data bagian yang diterima dalam header ETag yang dikembalikan kepada pengguna.
OSS menghitung hash MD5 dari data yang diunggah dan membandingkannya dengan hash MD5 yang dihitung oleh SDK. Jika kedua hash MD5 berbeda, kode kesalahan InvalidDigest dikembalikan.
Selesaikan unggah multi-bagian.
Setelah semua bagian diunggah, panggil metode Client.CompleteMultipartUpload untuk menggabungkan bagian-bagian menjadi satu objek lengkap.
Contoh
Kode contoh berikut menunjukkan cara membagi file lokal besar menjadi beberapa bagian, mengunggah bagian-bagian tersebut ke bucket secara bersamaan, lalu menggabungkan bagian-bagian tersebut menjadi satu objek lengkap.
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"
)
// Tentukan variabel global.
var (
region string // Wilayah.
bucketName string // Nama bucket sumber.
objectName string // Nama objek sumber.
)
// Fungsi init digunakan untuk menginisialisasi parameter baris perintah.
func init() {
flag.StringVar(®ion, "region", "", "Wilayah tempat bucket berada.")
flag.StringVar(&bucketName, "bucket", "", "Nama bucket sumber.")
flag.StringVar(&objectName, "object", "", "Nama objek sumber.")
}
func main() {
// Parsing parameter baris perintah.
flag.Parse()
// Tentukan ID unggah.
var uploadId string
// Periksa apakah nama bucket sumber kosong.
if len(bucketName) == 0 {
flag.PrintDefaults()
log.Fatalf("parameter tidak valid, nama bucket sumber diperlukan")
}
// Periksa apakah wilayah kosong.
if len(region) == 0 {
flag.PrintDefaults()
log.Fatalf("parameter tidak valid, wilayah diperlukan")
}
// Periksa apakah nama objek sumber kosong.
if len(objectName) == 0 {
flag.PrintDefaults()
log.Fatalf("parameter tidak valid, nama objek sumber diperlukan")
}
// Muat konfigurasi default, dan atur penyedia kredensial dan wilayah.
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
// Buat klien OSS.
client := oss.NewClient(cfg)
// Mulai permintaan unggah multi-bagian.
initRequest := &oss.InitiateMultipartUploadRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
}
initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)
if err != nil {
log.Fatalf("gagal memulai unggah multi-bagian %v", err)
}
// Cetak hasil memulai unggah multi-bagian.
log.Printf("hasil inisiasi unggah multi-bagian:%#v\n", *initResult.UploadId)
uploadId = *initResult.UploadId
// Inisialisasi wait group dan mutex.
var wg sync.WaitGroup
var parts []oss.UploadPart
count := 3
var mu sync.Mutex
// Baca konten file lokal ke dalam memori. Ganti yourLocalFile dengan nama dan jalur file lokal sebenarnya.
file, err := os.Open("yourLocalFile")
if err != nil {
log.Fatalf("gagal membuka file lokal %v", err)
}
defer file.Close()
bufReader := bufio.NewReader(file)
content, err := io.ReadAll(bufReader)
if err != nil {
log.Fatalf("gagal membaca file lokal %v", err)
}
log.Printf("ukuran file: %d\n", len(content))
// Hitung ukuran setiap bagian.
chunkSize := len(content) / count
if chunkSize == 0 {
chunkSize = 1
}
// Mulai beberapa goroutine untuk mengunggah bagian.
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()
// Buat permintaan untuk mengunggah bagian.
partRequest := &oss.UploadPartRequest{
Bucket: oss.Ptr(bucketName), // Nama bucket tujuan.
Key: oss.Ptr(objectName), // Nama objek tujuan.
PartNumber: int32(partNumber), // Nomor bagian.
UploadId: oss.Ptr(uploadId), // ID unggah.
Body: bytes.NewReader(content[start:end]), // Konten bagian.
}
// Kirim permintaan untuk mengunggah bagian.
partResult, err := client.UploadPart(context.TODO(), partRequest)
if err != nil {
log.Fatalf("gagal mengunggah bagian %d: %v", partNumber, err)
}
// Catat hasil unggah bagian.
part := oss.UploadPart{
PartNumber: partRequest.PartNumber,
ETag: partResult.ETag,
}
// Gunakan mutex untuk melindungi data bersama.
mu.Lock()
parts = append(parts, part)
mu.Unlock()
}(i+1, start, end)
}
// Tunggu hingga semua goroutine selesai.
wg.Wait()
// Selesaikan permintaan unggah multi-bagian.
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("gagal menyelesaikan unggah multi-bagian %v", err)
}
// Cetak hasil penyelesaian unggah multi-bagian.
log.Printf("hasil penyelesaian unggah multi-bagian:%#v\n", result)
}
Skenario umum
Referensi
Untuk kode contoh lengkap unggah multi-bagian, lihat contoh GitHub.
Implementasi unggah multi-bagian lengkap melibatkan tiga operasi API berikut:
Untuk memulai peristiwa unggah multi-bagian, lihat InitiateMultipartUpload.
Untuk mengunggah sebuah bagian, lihat UploadPart.
Untuk menyelesaikan unggah multi-bagian, lihat CompleteMultipartUpload.
Untuk membatalkan peristiwa unggah multi-bagian, lihat AbortMultipartUpload.
Untuk mencantumkan bagian yang telah diunggah, lihat NewListPartsPaginator.
Untuk mencantumkan semua peristiwa unggah multi-bagian yang sedang berlangsung (peristiwa yang dimulai tetapi belum selesai atau dibatalkan), lihat NewListMultipartUploadsPaginator.