Thriftでバイナリデータをやりとりする方法。
以前、FlexでXML-RPCを利用していた時は、確かbase64にエンコードして返していたと思うので、
Thriftでも同様にバイナリデータはbase64にエンコードして返すようにします。
Thriftのソースを漁っていると TBase64Utils とかいうのを見つけたのですが、
どうせboost必須なフレームワークなのでboostを使ってエンコードしてみます。
インタフェースとして、
・サービス名を Test
・プロシージャ名を returnImage
・引数は画像ファイル名、戻り値はbase64エンコード文字列
を定義します。
1 2 3 4 5 |
#!/usr/bin/thrift service Test { string returnImage(1: string name) } |
画像ファイルを読み込んで、base64にエンコードするだけの処理です。
boostでbase64にエンコードする方法は以下のサイトを参考にさせていただきました。
B Lifeで行こう: boostでbase64のエンコード
ここではハンドラの部分のみ、自動生成部分は省略します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
class TestHandler : virtual public TestIf { public: TestHandler() { } void returnImage(std::string& _return, const std::string& name) { std::ifstream ifs; std::ostringstream oss; std::string str; ifs.open(name.c_str(), std::ios::in | std::ios::binary); if(!ifs.is_open()) { _return = ""; }else { oss<<ifs.rdbuf(); str = oss.str(); _return = encode_base64(str); } } std::string encode_base64(const std::string& src_data) { using namespace boost::archive::iterators; const int Base64_Column_Width = 76; typedef insert_linebreaks<base64_from_binary<transform_width< const char *, 6, 8> >, Base64_Column_Width> base64_encoder; // エンコードしたデータを格納 std::stringstream ost_base64; // エンコード処理 std::copy( base64_encoder(src_data.c_str()), base64_encoder(src_data.c_str() + src_data.length()), std::ostream_iterator<char>(ost_base64) ); std::string base64 = ost_base64.str(); // 末尾の長さ調整 while(((base64.length() % (Base64_Column_Width + 1)) % 4) > 0) { base64 += "="; } return base64; } }; |
次にクライアントを今回はPHPで書きます。
RPCで受け取ったbase64エンコード文字列をimgタグに埋め込んで画面に表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<?php $GLOBALS['THRIFT_ROOT'] = 'src'; $GEN_DIR = 'gen-php'; /** Include the Thrift base */ require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php'; /** Include the binary protocol */ require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php'; /** Include the socket layer */ require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocketPool.php'; /** Include the socket layer */ require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php'; /** Include the generated code */ require_once $GEN_DIR.'/test/Test.php'; require_once $GEN_DIR.'/test/test_types.php'; $transport = new TSocket('localhost', 9090); $client = new TestClient(new TBinaryProtocol($transport)); try { $transport->open(); $img = $client->returnImage("lenna.jpg"); /* $img に base64エンコード文字列が入る */ $transport->close(); }catch(Exception $e) { echo $e->getMessage(); } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="www.w3.org/1999/xhtml" lang="ja" xml:lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <title>Embed Base64 Image Test</title> </head> <body> <img src="data:image/jpg;base64,<?php echo $img ?>" /> </body> </html> |
こんな感じで一応上手く表示まで行うことができました。
サーバ側で画像処理を行った後、出力画像をクライアントに返す時などに使えます。
楽な方法なんですが、大きな画像データをやりとりするのには向いてないですね;;
もうちょっと良い方法を探してみます。
・関連記事
Thrift + OpenCV
Thrift::例外処理
Thriftインストール