全部产品
Search
文档中心

Object Storage Service:Unggah multi-bagian (C SDK)

更新时间:Nov 30, 2025

Object Storage Service (OSS) menyediakan fitur unggah multi-bagian yang memungkinkan Anda membagi objek besar menjadi beberapa bagian dan mengunggahnya secara independen. Setelah semua bagian diunggah, Anda dapat memanggil operasi CompleteMultipartUpload untuk menggabungkan bagian-bagian tersebut menjadi satu objek utuh, sehingga memungkinkan unggah yang dapat dilanjutkan.

Catatan penggunaan

  • Pada topik ini, digunakan titik akhir publik wilayah China (Hangzhou). Jika Anda mengakses OSS dari layanan Alibaba Cloud lainnya dalam wilayah yang sama dengan OSS, gunakan titik akhir internal. Untuk informasi selengkapnya mengenai wilayah dan titik akhir OSS, lihat Wilayah dan titik akhir.

  • Pada topik ini, instans OSSClient dibuat menggunakan titik akhir OSS. Jika Anda ingin membuat instans OSSClient menggunakan nama domain kustom atau Security Token Service (STS), lihat Inisialisasi (C SDK).

  • Untuk menyelesaikan proses unggah multi-bagian—yang mencakup operasi InitiateMultipartUpload, UploadPart, dan CompleteMultipartUpload—Anda harus memiliki izin oss:PutObject. Untuk informasi selengkapnya, lihat Berikan izin kustom kepada RAM user.

Proses unggah multi-bagian

Untuk mengunggah objek menggunakan unggah multi-bagian, lakukan langkah-langkah berikut:

  1. Inisialisasi event unggah multi-bagian.

    Panggil metode oss_init_multipart_upload. Metode ini mengembalikan upload ID yang bersifat unik secara global yang dibuat oleh OSS.

  2. Unggah bagian-bagian.

    Panggil oss_upload_part_from_file untuk mengunggah bagian-bagian tersebut.

    Catatan
    • Untuk uploadId tertentu, nomor bagian mengidentifikasi posisi suatu bagian dalam objek lengkap. Jika Anda mengunggah bagian baru dengan nomor bagian yang sama dengan bagian yang sudah ada, bagian yang sudah ada akan ditimpa.

    • OSS menyertakan hash MD5 dari data bagian yang diterima dalam header ETag pada respons.

    • OSS menghitung hash MD5 dari data yang diunggah dan membandingkannya dengan hash MD5 yang dihitung oleh SDK. Jika kedua hash tidak cocok, OSS mengembalikan kode kesalahan InvalidDigest.

  3. Selesaikan unggah multi-bagian.

    Setelah semua bagian diunggah, panggil metode oss_complete_multipart_upload untuk menggabungkannya menjadi satu file utuh.

Contoh unggah multi-bagian lengkap

Contoh berikut menunjukkan proses unggah multi-bagian lengkap:

#include "oss_api.h"
#include "aos_http_io.h"
#include <sys/stat.h>
/* Tetapkan yourEndpoint ke Endpoint wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), tetapkan Endpoint ke https://oss-cn-hangzhou.aliyuncs.com. */
const char *endpoint = "yourEndpoint";

/* Masukkan nama bucket, misalnya examplebucket. */
const char *bucket_name = "examplebucket";
/* Masukkan path lengkap objek. Path tidak boleh mengandung nama bucket. Misalnya, masukkan exampledir/exampleobject.txt. */
const char *object_name = "exampledir/exampleobject.txt";
/* Masukkan path lengkap file lokal. */
const char *local_filename = "yourLocalFilename";
/* Tetapkan yourRegion ke wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), tetapkan Region ke cn-hangzhou. */
const char *region = "yourRegion";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* Inisialisasi tipe aos_string_t dengan string char*. */
    aos_str_set(&options->config->endpoint, endpoint);
    /* Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode ini, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah disetel. */    
    aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
    aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
    // Konfigurasikan dua parameter berikut.
    aos_str_set(&options->config->region, region);
    options->config->signature_version = 4;
    /* Tentukan apakah akan menggunakan CNAME untuk mengakses OSS. Nilai 0 berarti CNAME tidak digunakan. */
    options->config->is_cname = 0;
    /* Tetapkan parameter jaringan, seperti periode timeout. */
    options->ctl = aos_http_controller_create(options->pool, 0);
}
int64_t get_file_size(const char *file_path)
{
    int64_t filesize = -1;
    struct stat statbuff;
    if(stat(file_path, &statbuff) < 0){
        return filesize;
    } else {
        filesize = statbuff.st_size;
    }
    return filesize;
}
int main(int argc, char *argv[])
{
    /* Pada titik masuk program, panggil metode aos_http_io_initialize untuk menginisialisasi resource global, seperti jaringan dan memori. */
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }
    /* Pool memori (pool) untuk manajemen memori. Ini setara dengan apr_pool_t. Kode implementasinya berada di pustaka apr. */
    aos_pool_t *pool;
    /* Buat pool memori baru. Parameter kedua adalah NULL, yang menunjukkan bahwa pool ini tidak mewarisi dari pool memori lain. */
    aos_pool_create(&pool, NULL);
    /* Buat dan inisialisasi opsi. Parameter ini mencakup konfigurasi global seperti endpoint, access_key_id, access_key_secret, is_cname, dan curl. */
    oss_request_options_t *oss_client_options;
    /* Alokasikan memori untuk opsi dalam pool memori. */
    oss_client_options = oss_request_options_create(pool);
    /* Inisialisasi opsi klien, oss_client_options. */
    init_options(oss_client_options);
    /* Inisialisasi parameter. */
    aos_string_t bucket;
    aos_string_t object;
    oss_upload_file_t *upload_file = NULL;
    aos_string_t upload_id;   
    aos_table_t *headers = NULL;
    aos_table_t *complete_headers = NULL;
    aos_table_t *resp_headers = NULL;
    aos_status_t *resp_status = NULL; 
    aos_str_set(&bucket, bucket_name);
    aos_str_set(&object, object_name);
    aos_str_null(&upload_id);
    headers = aos_table_make(pool, 1);
    complete_headers = aos_table_make(pool, 1);
    int part_num = 1;
    /* Inisialisasi unggah multi-bagian dan peroleh upload ID. */
    resp_status = oss_init_multipart_upload(oss_client_options, &bucket, &object, &upload_id, headers, &resp_headers);
    /* Periksa apakah inisialisasi unggah multi-bagian berhasil. */
    if (aos_status_is_ok(resp_status)) {
        printf("Init multipart upload succeeded, upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    } else {
        printf("Init multipart upload failed, upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    }
    /* Unggah bagian-bagian. */
    int64_t file_length = 0;
    int64_t pos = 0;
    aos_list_t complete_part_list;
       oss_complete_part_content_t* complete_content = NULL;
    char* part_num_str = NULL;
    char* etag = NULL;
    aos_list_init(&complete_part_list);
    file_length = get_file_size(local_filename);
    while(pos < file_length) {
        upload_file = oss_create_upload_file(pool);
        aos_str_set(&upload_file->filename, local_filename);
        upload_file->file_pos = pos;
        pos += 100 * 1024;
        upload_file->file_last = pos < file_length ? pos : file_length;
        resp_status = oss_upload_part_from_file(oss_client_options, &bucket, &object, &upload_id, part_num++, upload_file, &resp_headers);

        /* Simpan nomor bagian dan ETag. */
        complete_content = oss_create_complete_part_content(pool);
        part_num_str = apr_psprintf(pool, "%d", part_num-1);
        aos_str_set(&complete_content->part_number, part_num_str);
        etag = apr_pstrdup(pool,
        (char*)apr_table_get(resp_headers, "ETag"));
        aos_str_set(&complete_content->etag, etag);
        aos_list_add_tail(&complete_content->node, &complete_part_list);

        if (aos_status_is_ok(resp_status)) {
            printf("Multipart upload part from file succeeded\n");
        } else {
            printf("Multipart upload part from file failed\n");
        }
    }

    /* Selesaikan unggah multi-bagian. */
    resp_status = oss_complete_multipart_upload(oss_client_options, &bucket, &object, &upload_id,
            &complete_part_list, complete_headers, &resp_headers);
    /* Periksa apakah unggah multi-bagian telah selesai. */
    if (aos_status_is_ok(resp_status)) {
        printf("Complete multipart upload from file succeeded, upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    } else {
        printf("Complete multipart upload from file failed\n");
    }
    /* Hancurkan pool memori. Ini melepaskan memori yang dialokasikan untuk setiap resource selama permintaan. */
    aos_pool_destroy(pool);
    /* Lepaskan resource global yang sebelumnya dialokasikan. */
    aos_http_io_deinitialize();
    return 0;
}

Saat memanggil operasi oss_complete_multipart_upload, Anda harus menyediakan nilai ETag setiap bagian. Nilai-nilai ini dapat diperoleh dengan salah satu dari dua cara berikut:

  • Saat mengunggah setiap bagian, respons berisi nilai ETag untuk bagian tersebut. Anda dapat menyimpan nilai ini dan menggunakannya nanti. Contoh di atas menggunakan metode ini.

  • Panggil operasi oss_list_upload_part untuk mengambil nilai ETag dari bagian-bagian yang sebelumnya diunggah.

Membatalkan event unggah multi-bagian

Kode berikut menunjukkan cara membatalkan event unggah multi-bagian.

#include "oss_api.h"
#include "aos_http_io.h"
/* Tetapkan yourEndpoint ke titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), tetapkan titik akhir ke https://oss-cn-hangzhou.aliyuncs.com. */
const char *endpoint = "yourEndpoint";

/* Tentukan nama bucket. Misalnya, examplebucket. */
const char *bucket_name = "examplebucket";
/* Tentukan path lengkap objek. Path lengkap tidak boleh mengandung nama bucket. Misalnya, exampledir/exampleobject.txt. */
const char *object_name = "exampledir/exampleobject.txt";
/* Tetapkan yourRegion ke wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), tetapkan wilayah ke cn-hangzhou. */
const char *region = "yourRegion";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* Inisialisasi tipe aos_string_t dengan string char*. */
    aos_str_set(&options->config->endpoint, endpoint);
    /* Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode ini, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah disetel. */    
    aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
    aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
    // Konfigurasikan dua parameter berikut.
    aos_str_set(&options->config->region, region);
    options->config->signature_version = 4;
    /* Menentukan apakah akan menggunakan CNAME untuk mengakses OSS. 0 berarti CNAME tidak digunakan. */
    options->config->is_cname = 0;
    /* Tetapkan parameter jaringan, seperti periode timeout. */
    options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
    /* Panggil metode aos_http_io_initialize pada titik masuk program untuk menginisialisasi resource global, seperti jaringan dan memori. */
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }
    /* Pool memori (pool) untuk manajemen memori setara dengan apr_pool_t. Kode implementasinya berada di pustaka apr. */
    aos_pool_t *pool;
    /* Buat pool memori baru. Parameter kedua adalah NULL, yang menunjukkan bahwa pool memori baru ini tidak mewarisi dari pool memori lain. */
    aos_pool_create(&pool, NULL);
    /* Buat dan inisialisasi opsi. Parameter ini berisi informasi konfigurasi global, seperti endpoint, access_key_id, access_key_secret, is_cname, dan curl. */
    oss_request_options_t *oss_client_options;
    /* Alokasikan memori untuk opsi dalam pool memori. */
    oss_client_options = oss_request_options_create(pool);
    /* Inisialisasi opsi klien oss_client_options. */
    init_options(oss_client_options);
    /* Inisialisasi parameter. */
    aos_string_t bucket;
    aos_string_t object;
    aos_string_t upload_id;   
    aos_table_t *headers = NULL;
    aos_table_t *resp_headers = NULL;
    aos_status_t *resp_status = NULL; 
    aos_str_set(&bucket, bucket_name);
    aos_str_set(&object, object_name);
    aos_str_null(&upload_id);
    /* Inisialisasi unggah multi-bagian untuk memperoleh upload ID (upload_id). */
    resp_status = oss_init_multipart_upload(oss_client_options, &bucket, &object, &upload_id, headers, &resp_headers);
    /* Periksa apakah inisialisasi unggah multi-bagian berhasil. */
    if (aos_status_is_ok(resp_status)) {
        printf("Init multipart upload succeeded, upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    } else {
        printf("Init multipart upload failed, upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    }
    /* Batalkan unggah multi-bagian. */
    resp_status = oss_abort_multipart_upload(oss_client_options, &bucket, &object, &upload_id, &resp_headers);
    /* Periksa apakah pembatalan unggah multi-bagian berhasil. */
    if (aos_status_is_ok(resp_status)) {
        printf("Abort multipart upload succeeded, upload_id::%.*s\n", 
               upload_id.len, upload_id.data);
    } else {
        printf("Abort multipart upload failed\n"); 
    }
    /* Hancurkan pool memori. Ini melepaskan memori yang dialokasikan untuk resource selama permintaan. */
    aos_pool_destroy(pool);
    /* Lepaskan resource global yang sebelumnya dialokasikan. */
    aos_http_io_deinitialize();
    return 0;
}
Catatan

Setelah event unggah multi-bagian dibatalkan, upload ID tidak dapat digunakan untuk operasi apa pun, dan bagian-bagian yang telah diunggah juga akan dihapus.

Referensi