Layanan Penyimpanan Objek (Object Storage Service/OSS) menyediakan fitur unggah multi-bagian untuk objek besar. Proses ini melibatkan pemisahan objek besar menjadi bagian-bagian yang lebih kecil, mengunggahnya secara independen, lalu memanggil API CompleteMultipartUpload untuk menggabungkan bagian-bagian tersebut menjadi satu objek utuh, sehingga memungkinkan unggah yang dapat dilanjutkan.
Catatan
-
Topik ini menggunakan titik akhir publik wilayah China (Hangzhou). Untuk mengakses OSS dari layanan Alibaba Cloud lainnya dalam wilayah yang sama, gunakan titik akhir internal. Untuk detail wilayah dan titik akhir yang didukung, lihat Regions and Endpoints.
-
Pada topik ini, kredensial akses diperoleh dari variabel lingkungan. Untuk informasi selengkapnya, lihat 配置访问凭证.
-
Topik ini menunjukkan cara membuat instans OSSClient dengan titik akhir OSS. Untuk konfigurasi alternatif, seperti menggunakan domain kustom atau melakukan autentikasi dengan kredensial dari Security Token Service (STS), lihat Client configuration.
-
Unggah multi-bagian menggunakan InitiateMultipartUpload, UploadPart, dan CompleteMultipartUpload. Anda harus memiliki izin
oss:PutObject. Grant custom access policies to a RAM user.
Proses unggah multi-bagian
Unggah multi-bagian terdiri dari tiga langkah:
-
Inisialisasi unggah multi-bagian.
Panggil ossClient.initiateMultipartUpload. OSS akan mengembalikan upload ID yang unik secara global.
-
Unggah bagian-bagian.
Panggil ossClient.uploadPart untuk mengunggah data bagian.
Catatan-
Nomor bagian mengidentifikasi posisi suatu bagian dalam objek. Mengunggah data dengan nomor bagian yang sama akan menimpa bagian yang sudah ada.
-
OSS mengembalikan hash MD5 dari data bagian yang diterima dalam header respons ETag.
-
OSS menghitung hash MD5 dari data yang diunggah dan membandingkannya dengan hash yang dihitung oleh SDK. Ketidakcocokan akan mengembalikan kode kesalahan InvalidDigest.
-
-
Selesaikan unggah multi-bagian.
Setelah semua bagian diunggah, panggil ossClient.completeMultipartUpload untuk menggabungkan bagian-bagian tersebut menjadi satu objek utuh.
Kode contoh
Contoh berikut menunjukkan proses lengkap unggah multi-bagian:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.internal.Mimetypes;
import com.aliyun.oss.model.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) throws Exception {
// Gunakan titik akhir wilayah China (Hangzhou) sebagai contoh. Tentukan titik akhir yang sebenarnya.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Tentukan nama bucket, misalnya examplebucket.
String bucketName = "examplebucket";
// Tentukan path lengkap objek, misalnya exampledir/exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket.
String objectName = "exampledir/exampleobject.txt";
// Path file lokal yang akan diunggah.
String filePath = "D:\\localpath\\examplefile.txt";
// Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou.
String region = "cn-hangzhou";
// Buat instans OSSClient.
// Setelah instans OSSClient tidak lagi digunakan, panggil metode shutdown untuk melepaskan sumber daya.
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// Buat objek InitiateMultipartUploadRequest.
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
// Buat objek ObjectMetadata dan atur Content-Type.
ObjectMetadata metadata = new ObjectMetadata();
if (metadata.getContentType() == null) {
metadata.setContentType(Mimetypes.getInstance().getMimetype(new File(filePath), objectName));
}
System.out.println("Content-Type: " + metadata.getContentType());
// Ikat metadata ke permintaan unggah.
request.setObjectMetadata(metadata);
// Inisialisasi unggah multi-bagian.
InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
// Kembalikan upload ID.
String uploadId = upresult.getUploadId();
// partETags adalah kumpulan objek PartETag. Objek PartETag terdiri dari ETag dan nomor bagian suatu bagian.
List<PartETag> partETags = new ArrayList<PartETag>();
// Ukuran setiap bagian. Ini digunakan untuk menghitung jumlah bagian. Satuan: byte.
// Ukuran bagian minimum adalah 100 KB, dan ukuran maksimum adalah 5 GB. Ukuran bagian terakhir dapat lebih kecil dari 100 KB.
// Atur ukuran bagian menjadi 1 MB.
final long partSize = 1 * 1024 * 1024L;
// Hitung jumlah bagian berdasarkan ukuran data yang akan diunggah. Kode berikut memberikan contoh cara memperoleh ukuran data yang akan diunggah dari file lokal menggunakan File.length().
final File sampleFile = new File(filePath);
long fileLength = sampleFile.length();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// Iterasi melalui bagian-bagian dan unggah.
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(objectName);
uploadPartRequest.setUploadId(uploadId);
// Atur aliran bagian yang akan diunggah.
// Kode berikut memberikan contoh cara membuat objek FileInputStream dari file lokal dan melewati data tertentu menggunakan metode InputStream.skip().
InputStream instream = new FileInputStream(sampleFile);
instream.skip(startPos);
uploadPartRequest.setInputStream(instream);
// Atur ukuran bagian.
uploadPartRequest.setPartSize(curPartSize);
// Atur nomor bagian. Setiap bagian yang diunggah memiliki nomor bagian yang berkisar antara 1 hingga 10.000. Jika nomor bagian tidak dalam rentang tersebut, OSS akan mengembalikan kode kesalahan InvalidArgument.
uploadPartRequest.setPartNumber(i + 1);
// Bagian tidak perlu diunggah secara berurutan. Bahkan dapat diunggah dari client yang berbeda. OSS akan mengurutkan bagian berdasarkan nomor bagian untuk membuat objek utuh.
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
// Setelah setiap bagian diunggah, respons OSS mencakup PartETag. PartETag disimpan dalam partETags.
partETags.add(uploadPartResult.getPartETag());
// Tutup aliran.
instream.close();
}
// Buat objek CompleteMultipartUploadRequest.
// Saat menyelesaikan unggah multi-bagian, Anda harus menyediakan semua partETags yang valid. Setelah OSS menerima partETags yang diajukan, OSS akan memverifikasi validitas setiap bagian. Setelah semua bagian diverifikasi, OSS akan menggabungkan bagian-bagian tersebut menjadi satu objek utuh.
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
// Selesaikan unggah multi-bagian.
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
System.out.println("Unggah berhasil, ETag: " + completeMultipartUploadResult.getETag());
} catch (OSSException oe) {
System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
+ "tetapi ditolak dengan respons kesalahan karena suatu alasan.");
System.out.println("Pesan Kesalahan:" + oe.getErrorMessage());
System.out.println("Kode Kesalahan:" + oe.getErrorCode());
System.out.println("ID Permintaan:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Terjadi ClientException, yang berarti client mengalami "
+ "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
+ "seperti tidak dapat mengakses jaringan.");
System.out.println("Pesan Kesalahan:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
Skenario umum
Atur metadata saat menginisialisasi unggah multi-bagian
Atur izin akses objek saat menyelesaikan unggah multi-bagian
Otomatis proses part ETags saat menyelesaikan unggah multi-bagian
Batalkan event unggah multi-bagian
Cantumkan bagian yang diunggah
Cantumkan event unggah multi-bagian
Lakukan unggah multi-bagian untuk aliran jaringan atau aliran data
Referensi
-
Kode contoh lengkap: Contoh GitHub.
-
Unggah multi-bagian melibatkan tiga operasi API:
-
Inisialisasi unggah multi-bagian: InitiateMultipartUpload.
-
Unggah bagian: UploadPart.
-
Selesaikan unggah multi-bagian: CompleteMultipartUpload.
-
-
Batalkan unggah multi-bagian: AbortMultipartUpload.
-
Cantumkan bagian yang diunggah: ListParts.
-
Cantumkan unggah multi-bagian yang sedang berlangsung: ListMultipartUploads.