9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHP(CakePHP)からGoogleCloudStorageを利用する

Last updated at Posted at 2015-06-01

前提条件

google-api-php-clientの準備

私は今回アプリケーションのルート(appと同階層)のvendorsを使用しました。app/Vendorとどう違うのかよくわかってません。
DLしたクライアントのsrc/Googleをvendorsの下にコピー。
app/Config/bootstrap.phpに以下の行を追加。

bootstrap.php
require_once(ROOT.DS."vendors/Google/autoload.php");

認証

今回はGoogleCloudStorageを扱うためのモデルをひとつ作成しました。
GoogleDevelopersConsoleの左カラム、APIと認証>認証情報より新しいクライアントIDを作成。
今回はユーザーに認証を求めず、PHPアプリケーション越しの操作となりますのでサービスアカウントを作成。
JSONキーを利用しますのでそちらを選択してください。

参考にしたサイトがこちら:メモ用紙
実際に書いたソースが以下。

Storage.php
    function __construct()
    {
        $this->client = new Google_Client();
        $this->client->setApplicationName('My Application');
        
        $this->client->setClientId($this->client_id);
        $this->client->setAssertionCredentials(new Google_Auth_AssertionCredentials($this->service_account_name, array(
            Google_Service_Storage::DEVSTORAGE_READ_WRITE
        ), file_get_contents(ROOT.DS."vendors/key/" . $this->key_file)));
    }

CakePHPのAppModel継承クラスなのでstaticの使い方はしませんでした。
コントローラからはふつうに$this->Storage->get()とかで使う想定です。

ファイルアップロード

Storage.php
public function upload($filename,$binary)
    {
        $contentType="";
        if(strncmp($binary,'89 50 4E 47',11)){
            $contentType="png";
        }else if(strncmp($binary,'FF D8 FF',8)){
            $contentType="jpeg";
        }else if(strncmp($binary,'47 49 46 38',11)){
            $contentType="gif";
        }else{
            return false;
        }
        
        // ストレージサービスを作成する
        $storage = new Google_Service_Storage($this->client);
        
        // アップロードするファイル名とデータ
        $name = $filename.'.'.$contentType;
        $data = $binary;
        
        // ストレージオブジェクトを作成する
        $obj = new Google_Service_Storage_StorageObject();
        $obj->setName($name);
        
        // アップロードする
        $result=$storage->objects->insert($this->default_bucket_name, $obj, [
            'name' => $name,
            'data' => $data,
            'uploadType' => 'media',
            'mimeType' => 'image/'.$contentType,
            'predefinedAcl' => 'publicread'
        ]);
    }

わざわざバイナリ読んで拡張子の判定してるのはちょっとこちらの都合です。
$_FILESそのままもらえるならファイル名の末尾取ればいいと思います。

27行目、$storage->objects->insertの第三引数について。
この後getメソッドを書いてPHP越しに画像を表示することを目標としていますので、mineTypeとpredefinedAclは設定が必要です。
mineTypeは設定しないと自動でapplication/octet-streamになってしまい、ブラウザで表示できませんでした。

参考:stackoverflow

ファイル表示

Storage.php
    public function get($name){
        // ストレージサービスを作成する
        $storage = new Google_Service_Storage($this->client);
        
        // ストレージオブジェクトを作成する
        $obj = new Google_Service_Storage_StorageObject();
        
        // 取得する
        $data = $storage->objects->get($this->default_bucket_name, $name);
        
        // 表示する
        header("Content-Type:".$data->getContentType());
        $content=file_get_contents($data->getMediaLink());
        echo $content;
    }

ここは割と素直に取得→表示、です。
upload時点でpredefinedAclを指定していない場合、ファイルの一般公開がされていませんので、file_get_contentsができない(権限がない)状態になります。

というわけで以上!
認証部分でハマってstackoverflow見に行った時、コメント3の「俺もそこで2日無駄にした……」みたいなコメントに癒やされました。
当方の場合は、導入したクライアントのバージョンが古かったのが問題でした(´@ω@`)

9
7
1

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
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?