Object Body のアップロード

Object Body としてファイルをアップロードすると、Object とファイルを紐付けて管理できます。Object Body の機能概要については、Object Body のアクセス をご覧ください。

Thing SDK Embedded は、以下の 2 種類の Object Body アップロード方法を提供しています。

いずれの方法でも、アップロード完了と同時に、Object に紐付く Object Body がアップロードしたデータに入れ替わります。このとき、既存の Object Body がある場合は、自動的に削除されます。また、同時更新となった場合は、後からアップロードが完了したデータになります(Object Body には楽観的ロックの仕組みはありません)。

分割アップロードでは、各 Object Body にサイズの上限はなく、合計サイズが料金プランのストレージ上限に達するまで格納できます。一括アップロードでは、100 MB までです(ただし、サーバーの安定動作のため、1 回のアップロードリクエストは 1 分程度までを目安としてください)。

1 回の転送サイズを大きくする場合、初期化の際に指定した バッファーサイズ にご注意ください。1 回の API 呼び出しでの転送サイズと、HTTP ヘッダー等のリクエストに必要なサイズの合計は、初期化で指定したバッファーサイズ以下である必要があります。

分割アップロード

Object Body をアップロードする例を以下に挙げます。

/* Set object body parameters. */
#define OBJECT_ID "STATUS_TEMPERATURE"
#define CONTENT_TYPE "application/octet-stream"

char OBJECT_BODY1[] = {
  0x31, 0x32, 0x33, 0x00, 0x34, 0x35, 0x36, 0x00, 0x37, 0x38, 0x39, 0x00
};
char OBJECT_BODY2[] = {
  0x36, 0x35, 0x34, 0x00, 0x33, 0x32, 0x31, 0x00
};
char uploadID[KII_UPLOADID_SIZE + 1];
kii_chunk_data_t chunkData1, chunkData2;

/* Set bucket parameters. */
kii_bucket_t bucket;
memset(&bucket, 0x00, sizeof(kii_bucket_t));
bucket.scope = KII_SCOPE_THING;
bucket.bucket_name = "myBucket";
bucket.scope_id = "VENDOR_THING_ID:rBnvSPOXBDF9r29GJeGS";

/* Upload the object body in chunks. */
ret = kii_object_init_upload_body(&kii, &bucket, OBJECT_ID, uploadID);
if (ret != 0) {
  /* Handle the error. */
  return;
}

/* Set the first chunk. */
chunkData1.body_content_type = CONTENT_TYPE;
chunkData1.position = 0;
chunkData1.length = sizeof(OBJECT_BODY1) / sizeof(OBJECT_BODY1[0]);
chunkData1.total_length = sizeof(OBJECT_BODY1) / sizeof(OBJECT_BODY1[0]) + sizeof(OBJECT_BODY2) / sizeof(OBJECT_BODY2[0]);
chunkData1.chunk = OBJECT_BODY1;

/* Upload the first chunk. */
ret = kii_object_upload_body(&kii, &bucket, OBJECT_ID, uploadID, &chunkData1);
if (ret != 0) {
  /* Handle the error. */
  return;
}

/* Set the second chunk. */
chunkData2.body_content_type = CONTENT_TYPE;
chunkData2.position = chunkData1.length;
chunkData2.length = sizeof(OBJECT_BODY2) / sizeof(OBJECT_BODY2[0]);
chunkData2.total_length = chunkData1.total_length;
chunkData2.chunk = OBJECT_BODY2;

/* Upload the second chunk. */
ret = kii_object_upload_body(&kii, &bucket, OBJECT_ID, uploadID, &chunkData2);
if (ret != 0) {
  /* Handle the error. */
  return;
}

/* Finalize the upload. */
ret = kii_object_commit_upload(&kii, &bucket, OBJECT_ID, uploadID, 1);
if (ret != 0) {
  /* Handle the error. */
  return;
}

分割アップロードでは、チャンクと呼ばれる単位で Object Body を分割して実行します。この例では、Object Body を 2 つのチャンクに分割してアップロードします。

サンプルコードは、以下の 3 種類の API の呼び出しで構成されます。4 回の API 呼び出し中、2 回はチャンクのアップロードのために同じ API を使っています。

  • kii_object_init_upload_body

    Object Body のアップロードを開始します。Object Body のアップロードを行うため、Object はあらかじめサーバー上に作成しておく必要があります。

    アップロード対象の Object は、kii_bucket_t 構造体と Object の ID で指定します。Bucket の指定方法は、Object の作成 をご覧ください。

    最後の引数は、アップロード ID を返す領域へのポインタです。後続の API では、取得した アップロード ID を使ってリクエストします。最低、KII_UPLOADID_SIZE + 1 バイトの領域を確保してください。

    このサンプルコードでは省略していますが、アップロード ID の取得後、エラーなどにより処理を中止する場合は、できるだけ kii_object_commit_upload を使ってロールバックするように実装してください。

  • kii_object_upload_body

    Object Body のデータのチャンクをアップロードして、アップロード済みのデータに追加します。この API を実行しても、まだ次のチャンクを受け付け可能な状態になっており、Object Body は書き換わっていません。

    アップロード対象の Object は kii_bucket_t 構造体、Object の ID、アップロード ID の 3 つで表現します。

    アップロード対象のデータのチャンクは、以下の kii_chunk_data_t 構造体で指定します。

    メンバー 説明
    body_content_type データの Content-Type を "type/subtype" の形式の文字列で指定します。すべてのチャンクで同じ文字列を指定します。Kii Cloud に送信された Content-Type は、ダウンロード時や、公開された Object Body をブラウザで参照するときに使用されます。
    position Object Body のアップロード開始位置です。初めのチャンクでは 0、2 回目以降は前回までのアップロードサイズの合計を指定します。
    length このチャンクに含まれるデータの長さをバイト単位で指定します。chunk が指すデータの有効なサイズです。
    total_length すべてのチャンクを結合した際の、Object Body の全体サイズを指定します。
    chunk このチャンクに含まれるデータへのポインタです。

    kii_object_upload_body は、データの全体をアップロードし終わるまで、繰り返して呼ぶことができます。

  • kii_object_commit_upload

    アップロードされた Object Body をコミットするか、キャンセルするかを指定します。

    引数ではアップロード対象の Object を kii_bucket_t 構造体、Object の ID、アップロード ID の 3 つで表現します。

    最後の引数が 1 以上の場合、アップロードがコミットされ、新しい Object Body に差し替わります。0 の場合、アップロードはキャンセルされ、Object Body は元のままです。

このサンプルでは、動作テストのため、合計 24 バイトの Object Body を 2 つのチャンクに分けてアップロードしています。OBJECT_BODY1 に格納された 12 バイトを 1 回目の kii_object_upload_body() の呼び出しで、OBJECT_BODY2 に格納された 8 バイトを 2 回目の kii_object_upload_body() の呼び出しでそれぞれ登録します。最後にコミット操作を行うと、これらは連続した 24 バイトの Object Body として登録されます。

各 API の呼び出しの間に Thing のプロセスのシャットダウンが入るようなケースでも、アップロード ID やチャンクの位置などが正しく管理できれば登録できます。これにより、大きな Object Body でも安全にアップロードすることができます。

一括アップロード

分割を行わず、1 回の API 呼び出しで Object Body 全体をアップロードすることも可能です(ただし、特にサイズの大きなファイルを Kii Cloud にアップロードするケースなどにおいては分割アップロードを利用することを推奨します)。

一括アップロードを行う例を以下に挙げます。

/* Set object body parameters. */
#define OBJECT_ID "STATUS_TEMPERATURE"
#define CONTENT_TYPE "application/octet-stream"
#define OBJECT_LENGTH 12

char OBJECT_BODY[] = {
  0x31, 0x32, 0x33, 0x00, 0x34, 0x35, 0x36, 0x00, 0x37, 0x38, 0x39, 0x00
};

/* Set bucket parameters. */
kii_bucket_t bucket;
memset(&bucket, 0x00, sizeof(kii_bucket_t));
bucket.scope = KII_SCOPE_THING;
bucket.bucket_name = "myBucket";
bucket.scope_id = "VENDOR_THING_ID:rBnvSPOXBDF9r29GJeGS";

/* Upload the object body. */
ret = kii_object_upload_body_at_once(&kii, &bucket, OBJECT_ID, CONTENT_TYPE, OBJECT_BODY, OBJECT_LENGTH);
if (ret != 0) {
  /* Handle the error. */
  return;
}

kii_object_upload_body_at_once 関数を使用すると、指定されたバッファーの内容を Object Body としてアップロードします。1 回の API の呼び出しで、Object Body の全体をアップロードしてサーバー上の Object Body を更新します。Object はあらかじめサーバー上に作成しておく必要があります。

アップロード対象の Object は、kii_bucket_t 構造体と Object の ID で指定します。Bucket の指定方法は、Object の作成 をご覧ください。

データの Content-Type を "type/subtype" の形式の文字列で指定します。Kii Cloud に送信された Content-Type は、ダウンロード時や、公開された Object Body をブラウザで参照するときに使用されます。