LoginSignup
1
0

More than 3 years have passed since last update.

CloudinaryのAdmin APIとSearch APIを使って、Clouidanryの画像を管理する

Last updated at Posted at 2020-04-22

この記事は

CloudinaryのUpload APIを使って、画像をアップロードする の続きで、CloudinaryのAdmin APIとSearch APIを試します。

環境の準備などは、前記事を参照でお願いします。

Admin API & Search APIとは

Admin API

Admin APIは、Cloudinaryの設定面を管理画面の代わりに操作できるAPIです。設定周りだけでなく、動画や画像(総じてAssetアセット)の操作もできます。Admin APIは1時間あたりの呼び出し回数に制限があります。

フリープランでは、1時間あたり500回です。
image.png

Search API

Search APIは、Cloudinary内に蓄積されたアセットをLuceneのようなクエリーを書いて検索するAPIです。さまざまなファイルの属性(ファイル名だけでなくタグ、登録・更新の時間、補足の説明など)を検索対象にして探すことができます。
APIのsearchメソッドはAdmin APIの一部なので、利用回数はAdminAPIと共有されます。認証方法、ページネーション、エラーハンドリングなどはAdmin APIと同じなので、ドキュメントを見るべし。

Admin APIで操作可能なオブジェクト

Admin APIでは、以下のものが操作可能です。(一部不明点あり)

Resources

アセットの操作ができます。アセットの検索する、情報を参照する、更新する、削除するなどの操作です。
メインの機能になります。

機能 説明
Get resources アセットを検索
Get resources by tag アセットをタグで検索
Get resources by context アセットをコンテキストで検索
Get resources in moderation queues 一時保留になっている画像を探す
Get the details of a single resource 1つのアセットの詳細を取る
Search for resources アセットを検索する(Search API)
Update details of an existing resource アセットの情報を更新する
Restore resources バックアップからリストア
Update access mode access modeを更新
Delete resources 複数のアセットを削除
Delete resources by tags タグを指定してアセットを削除

Transformations

変換を作ったり消したりできます。管理画面のここに表示される一覧のことです。
image.png

Upload mappings

URLで外部リソースを取り込むマッピングを作ったり消したり。APIでわざわざやらないような気もする。
image.png

Upload presets

アップロードしたときに変換されるプリセットを作ったり消したり。これも、APIでわざわざやらないような気もする。
image.png

Metadata fields

Cloudinaryで管理する全てのアセットに、共通のメタデータを定義する機能をAPIでやるのですね。
コンソールだと、設定メニューの右側にあるリンクから行ける機能です。
image.png

型を決めて、メタデータの箱を登録すると、各アセットにメタデータを登録できるようになると。(使うかな。。)
image.png

Folders

フォルダを作ったり消したり

Adaptive streaming profiles

(。´・ω・)ん?これはなんだ?
https://cloudinary.com/documentation/admin_api#adaptive_streaming_profiles

Tags

画像にタグをつけるのではなくて、システム内のタグの種類を見るだけ。

Usage

システムの利用状況(プラン、StorageやBandwidth)を確認する

Ping

いきてますかー?

詳細はこちらに。
https://cloudinary.com/documentation/admin_api

SDKに頼らずにHTTPSで直接実行してみる

Admin APIは、API KeyAPI Secretだけで接続することができます。Upload APIのように、パラメータから複雑な手順で生成するsignatureは不要です。使い方さえ覚えてしまえば、PostManやVS CodeのHTTP Clientでも実行可能です。

Admin APIの接続先

APIはAPIキーとAPIシークレットをURLに埋める形で作ります。最後のアクション部分を変えることで呼び出す処理が変わります。

Admin APIのURLのパターン
https://<API_KEY>:<API_SECRET>@api.cloudinary.com/v1_1/<CLOUD_NAME>/<ACTION>

:white_check_mark:自分の環境のURL
https://378xxx:eyhxxx@api.cloudinary.com/v1_1/kanaxx/

レスポンスヘッダーにAPIの実行回数に関する情報が含まれています。Headerから残り回数を読み取って残りが少なくなったら待機するか、エラーコードでエラー処理をするのか、どちらか実装しておきましょう。
上限が超えたときには、420: Rate limited.になります。

HTTP_Response_Header
X-FeatureRateLimit-Limit: 500
X-FeatureRateLimit-Remaining: 498
X-FeatureRateLimit-Reset: Sat, 18 Apr 2020 10:00:00 GMT

APIの実行回数は、時計の針が00分になるときに、全てリセットされる仕組みです。

コード

Admin APIの中で簡単な/usage Actionにリクエストを投げ込むPHPです。

admin-api.php
<?php
//各自設定
$cloudName='kanaxx';
$resourceType = 'image';
$apiKey = '37826219xxx';
$apiSecret = 'eyhlvE3t16l1WYxxx';

$api = "https://{$apiKey}:{$apiSecret}@api.cloudinary.com/v1_1/{$cloudName}/";

$usage = $api . '/usage';

// 以下、API実行部分
$ch = curl_init();

// オプションを設定
curl_setopt($ch, CURLOPT_URL, $usage); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($ch, CURLOPT_VERBOSE, 1);
// curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));

// API実行
$json = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

echo 'Response Code:' . $code . PHP_EOL;
echo $json . PHP_EOL;

$result = json_decode($json, true);
var_dump($result);

難しくないですね。
response code=200でないときだけ、ちゃんと対応をしましょう。

SDKを使う

前回同様、PHPのSDKを使ってCloudinaryをコントロールしてみます。管理コンソールでやればよさそうなものをやってもしょうがないので、画像の操作系だけやってみます。

admin-api-sdk.php
$api = new \Cloudinary\Api();

//1.使用量の確認
$usage = $api->usage();
//データ全体
var_export($usage);
//細かくみるなら、こんな感じで
echo 'plan = ' . $usage['plan'] . PHP_EOL;
echo 'storage =  ' . $usage['storage']['usage'] . PHP_EOL;
echo PHP_EOL;

//2.簡易な検索機能で画像を探す。
$resources = $api->resources([
    'max_results' => 10,
    'resource_type '=>'image',
    'type'=>'upload',
    'prefix'=>'upload-test/test'
]);
var_export($resources);

//各リソースは、'resource'キーに配列が入っている
foreach($resources['resources'] as $r){
    echo $r['public_id'] . PHP_EOL;
}

echo PHP_EOL;

//3.画像を1件だけ探すと情報がたくさんとれる。単数形なので注意
$resource = $api->resource('upload-test/test4_l8ro1n');
var_export($resource);
echo PHP_EOL;

//4.Cloudinary内のタグ一覧
$tags = $api->tags(['max_results'=>500]);
var_export($tags['tags']);


実行結果

SDKで実行したときは、PHPのオブジェクトにラップされて戻ってきます。

resources(複数形)の戻り

resources
 array (
      'public_id' => 'upload-test/test01',
      'format' => 'png',
      'version' => 1586779187,
      'resource_type' => 'image',
      'type' => 'upload',
      'created_at' => '2020-04-13T11:59:47Z',
      'bytes' => 1530,
      'width' => 150,
      'height' => 150,
      'access_mode' => 'public',
      'url' => 'http://res.cloudinary.com/kanaxx/image/upload/v1586779187/upload-test/test01.png',
      'secure_url' => 'https://res.cloudinary.com/kanaxx/image/upload/v1586779187/upload-test/test01.png',
    )

resource(単数)呼び出しの戻り方

resource
array(
   'public_id' => 'upload-test/test4_l8ro1n',
   'format' => 'png',
   'version' => 1587268817,
   'resource_type' => 'image',
   'type' => 'upload',
   'created_at' => '2020-04-19T04:00:17Z',
   'bytes' => 1433,
   'width' => 150,
   'height' => 150,
   'backup' => true,
   'access_mode' => 'public',
   'url' => 'http://res.cloudinary.com/kanaxx/image/upload/v1587268817/upload-test/test4_l8ro1n.png',
   'secure_url' => 'https://res.cloudinary.com/kanaxx/image/upload/v1587268817/upload-test/test4_l8ro1n.png',
   'next_cursor' => '38cb428ee5bce2c43ae9db1442eecf8579d95eebc82715ce87a4686467b70d23',
   'derived' =>  array (
    0 =>
    array (
      'transformation' => 't_media_lib_thumb',
      'format' => 'png',
      'bytes' => 1139,
      'id' => 'f00301b389c96f5ea828a696ae8a3f48',
      'url' => 'http://res.cloudinary.com/kanaxx/image/upload/t_media_lib_thumb/v1587268817/upload-test/test4_l8ro1n.png',
      'secure_url' => 'https://res.cloudinary.com/kanaxx/image/upload/t_media_lib_thumb/v1587268817/upload-test/test4_l8ro1n.png',
    ),
    1 =>
    array (
      'transformation' => 'a_hflip,w_200/a_45,g_south_west,l_pop_gazouha_image_desu,w_70',
      'format' => 'png',
      'bytes' => 6549,
      'id' => '6de1174745014ab48bca093fce6b6b58',
      'url' => 'http://res.cloudinary.com/kanaxx/image/upload/a_hflip,w_200/a_45,g_south_west,l_pop_gazouha_image_desu,w_70/v1587268817/upload-test/test4_l8ro1n.png',
      'secure_url' => 'https://res.cloudinary.com/kanaxx/image/upload/a_hflip,w_200/a_45,g_south_west,l_pop_gazouha_image_desu,w_70/v1587268817/upload-test/test4_l8ro1n.png',
    ),
    2 =>
    array (
      'transformation' => 'bo_3px_solid_blue,r_max,w_120',
      'format' => 'png',
      'bytes' => 3548,
      'id' => '662d3f6e8f9d759708128812e97cb073',
      'url' => 'http://res.cloudinary.com/kanaxx/image/upload/bo_3px_solid_blue,r_max,w_120/v1587268817/upload-test/test4_l8ro1n.png',
      'secure_url' => 'https://res.cloudinary.com/kanaxx/image/upload/bo_3px_solid_blue,r_max,w_120/v1587268817/upload-test/test4_l8ro1n.png',
    ),
    3 =>
    array (
      'transformation' => 'bo_2px_solid_red,w_100',
      'format' => 'png',
      'bytes' => 1172,
      'id' => 'e66d0e2d6304f57cd008ddb141bc07cd',
      'url' => 'http://res.cloudinary.com/kanaxx/image/upload/bo_2px_solid_red,w_100/v1587268817/upload-test/test4_l8ro1n.png',
      'secure_url' => 'https://res.cloudinary.com/kanaxx/image/upload/bo_2px_solid_red,w_100/v1587268817/upload-test/test4_l8ro1n.png',
    ),
  ),
))

Admin APIの2つのリソース系のメソッドの大きな違いは、Get the details of a single resource(単一public_idを指定)は、deliveredの画像の一覧が取れることですね。deliveredのリソースとは、元画像を元にして変換して増殖した分ということです。

Search API SDK

Search APIはAdmin APIの一部なのに、Admin APIと使い方が違います。しかも、PHP-SDKの公式マニュアルも微妙に間違えていたので注意です。

example_from_official_page
//https://cloudinary.com/documentation/search_api#syntax

//↓コンパイルエラーです
result = \Cloudinary\search->execute();

SDKのソースを調べてみましたが、new Search()で一度インスタンス化すれば使えそうです。
$searchインスタンスは内部にexpression()max_results()などのメソッドチェーンで渡した条件が保持されているので、インスタンスを使いまわすときには気を付けましょう。同一条件でページネーションしていくケース以外では、使いまわさないほうがよさそうです。

:warning: 例1と例2で使いまわすと痛い目に合います。(1件しか取れななくて1時間くらいハマりました)

SearchAPIのサンプルコード

<?php
require_once "vendor/autoload.php";
\Cloudinary::config([ 
    "cloud_name" => "kanaxx", "secure" => true,
    "api_key" => "37826219xxx", "api_secret" => "eyhlvE3t16l1WYgdxxx", 
]);


//例1. public_idを指定して検索
//public_id=aだと完全一致、public_id:aだと部分一致
$result = (new \Cloudinary\Search())
            ->max_results(10)
            ->expression('public_id=upload-test/test4_l8ro1n')
            ->execute();

var_export($result);
echo PHP_EOL;


//例2. 一番新しい画像を探す (order by created_at desc limit 1)
//Search APIだとMatch件数が取れるので、expressionを指定しないクエリーなし画像の総数が分かる
$search = new \Cloudinary\Search();
$result = $search
            ->max_results(1)
            ->sort_by('created_at','desc')
            ->execute();
var_export($result);
echo PHP_EOL;


//例3. フォルダ配下にあるファイルを検索
//pagenationのカーソルを使うためにmax=10で実行
$search = new \Cloudinary\Search();

//基本的な条件だけ先に組み立てておいて
$search->expression('folder=upload-test AND filename=api*')
        ->max_results(10)
        ->sort_by('created_at','desc');

$next = '';
$no = 0;
do{
    //カーソルの値を足してから、execute
    //この場合だけは、$searchインスタンスを使いまわしてよい。
    $result = $search->next_cursor($next)->execute();

    $resources = $result['resources']??[];
    echo count($resources) . '/' . $result['total_count'] . PHP_EOL;

    $next =  $result['next_cursor']??'';
    echo 'next cursor ==>' . $next . PHP_EOL;

    //画像の一覧
    foreach($resources as $resource){
        $no++;
        echo $no . ' ' . $resource['public_id'] .'|'. $resource['created_at'] . PHP_EOL;
    }
}while($next != '');


実行結果

例1

1件だけ取れるので、total_count=1で、resources配列に値が入ってきます。

Cloudinary\Api\Response::__set_state(array(
   'total_count' => 1,
   'time' => 116,
   'resources' =>
  array (
    0 =>
    array (
      'public_id' => 'upload-test/test4_l8ro1n',
      'folder' => 'upload-test',
      'filename' => 'test4_l8ro1n',
      'format' => 'png',
      'version' => 1587268817,
      'resource_type' => 'image',
      'type' => 'upload',
      'created_at' => '2020-04-19T04:00:17+00:00',
      'uploaded_at' => '2020-04-19T04:00:17+00:00',
      'bytes' => 1433,
      'backup_bytes' => 1433,
      'width' => 150,
      'height' => 150,
      'aspect_ratio' => 1.0,
      'pixels' => 22500,
      'url' => 'http://res.cloudinary.com/kanaxx/image/upload/v1587268817/upload-test/test4_l8ro1n.png',
      'secure_url' => 'https://res.cloudinary.com/kanaxx/image/upload/v1587268817/upload-test/test4_l8ro1n.png',
      'status' => 'active',
      'access_mode' => 'public',
      'access_control' => NULL,
      'etag' => 'e3ae356ead1e954aa25ff8fe77e344b3',
      'created_by' =>
      array (
        'access_key' => '378262191665246',
      ),
      'uploaded_by' =>
      array (
        'access_key' => '378262191665246',
      ),
    ),
  ),
))

例2の

total_count=448件のうち、一番新しい画像が1つだけ返ってきます。

array(
   'total_count' => 448,
   'time' => 785,
   'next_cursor' => 'f9f3441bf70cb7a277280e548b4a824ae34db3c441d2106674a7f3955a140748ecdd7b525feaf9ce0efcfaeba7926664',
   'resources' =>
  array (
    0 =>
    array (
      'public_id' => 'upload-test/api-context3',
      'folder' => 'upload-test',
      'filename' => 'api-context3',
      'format' => 'jpg',
      'version' => 1587475767,
      'resource_type' => 'image',
      'type' => 'upload',
      'created_at' => '2020-04-21T13:29:27+00:00',
      'uploaded_at' => '2020-04-21T13:29:27+00:00',
      'bytes' => 2639,
      'backup_bytes' => 2639,
      'width' => 150,
      'height' => 150,
      'aspect_ratio' => 1.0,
      'pixels' => 22500,
      'url' => 'http://res.cloudinary.com/kanaxx/image/upload/v1587475767/upload-test/api-context3.jpg',
      'secure_url' => 'https://res.cloudinary.com/kanaxx/image/upload/v1587475767/upload-test/api-context3.jpg',
      'status' => 'active',
      'access_mode' => 'public',
      'access_control' => NULL,
      'etag' => 'ef01d44d8742ad19cd34739f4ed25b9d',
      'created_by' =>
      array (
        'access_key' => '378262191665246',
      ),
      'uploaded_by' =>
      array (
        'access_key' => '378262191665246',
      ),
    ),
  ),
))

例3

全部で12件の結果を10件刻みで取得しました。next_cursorがemptyになったらbreakします。sort_by指定をしているので、新しい順に並んで取れます。

件数:12
next cursor ==>1bcfc7ba149c49ba483be2ccd755ed6e393aea3b6ed3708781dd309e6c7cc211cde9171c341dd21ea30f0dba4e5e0e34
1 upload-test/api-context3|2020-04-21T13:29:27+00:00
2 upload-test/api-context2|2020-04-21T13:29:21+00:00
3 upload-test/api-context1|2020-04-21T13:29:12+00:00
4 upload-test/api-accessmode02|2020-04-20T23:53:35+00:00
5 upload-test/api-accessmode03|2020-04-20T23:51:08+00:00
6 upload-test/api-accessmode01|2020-04-20T23:40:00+00:00
7 upload-test/api-tag03|2020-04-20T16:56:33+00:00
8 upload-test/api-tag02|2020-04-20T16:44:01+00:00
9 upload-test/api-tag01|2020-04-20T16:43:24+00:00
10 upload-test/api-test03|2020-04-20T16:39:15+00:00
件数:12
next cursor ==>
11 upload-test/api-test02|2020-04-20T16:38:20+00:00
12 upload-test/api-test01|2020-04-20T16:37:47+00:00

Admin APIとUpload APIの重複操作

今回、APIを調べていてAdmin APIUpload APIでどちらでもできるものがあったので、整理しておきます。Upload APIは回数制限がないので、どちらでもできるのであればUpload APIでやるほうがよさそうです。

操作 Admin API Upload API memo
画像登録 x o
名前変更 x o
画像の削除 複数 1つずつ
画像の検索 o x resource / search の2種類あり
情報取得 o x resource / resources で取得する情報に差があり
Tag操作 1つの画像に複数のタグを設定 複数の画像に1つのタグを設定
Context操作 1つの画像に設定 複数の画像に設定
AccessMode変更 x upload時に設定 RESTではできるのにSDKに実装されていない

まとめ

Cloudinaryファンとして、2つのAPIの使い方を簡単に書いてみましたけど、まぁ、あまり出番がないかもですねぇ。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0