RubyでAzure BLOB Storageにファイルをアップロードする

GYAOの窓際エンジニア　玉利です。

tsさん主導で、[汎用データ解析PFを作っている](http://qiita.com/tstakano-yj/items/21f78336a8a3aae50f82)のですが、Azure BLOB storageを使うことになりました。

それはそうと、今日も飯ネタです。おやすみ頂いて、夕方まで勉強会。5時過ぎに遅い昼ごはんを中華街でいただきました。

<img width="644" alt="スクリーンショット_2016_11_18_17_31.png" src="https://qiita-image-store.s3.amazonaws.com/0/113049/5ee2a7fe-d3ad-7db2-34f9-aef10379acc0.png">


今日いったのは、海員閣。昔、美味しんぼでサービス悪い店としてネタにされてましたが、雁屋哲さんがオーバーな人なので、私に言わせれば中国だったらかなり上のサービスです。いまだにコークスの窯で調理してるのはここくらいでしょう。横浜の海の男達の胃袋を支えてきた店ですので、盛りがいいです。味も昔ながらのもので、癒やされました。

さて、RailsからAzure Storageにデータを放り込む仕事をベトナムにお願いするわけですが、先にある程度いじっておきましょう。APIの使い方は[githubのレポジトリ](https://github.com/azure/azure-storage-ruby) に書いてあるのですが、私も初めてなので勉強です。

# BLOBって何？

私も初耳でした（素人ですみません）要は、大きいデータをどかんと置くときはコレがいいようです。例えば動画ファイルとか、パッケージファイル的なものとかです。

[WikiのBLOB説明](https://ja.wikipedia.org/wiki/%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%83%BB%E3%83%A9%E3%83%BC%E3%82%B8%E3%83%BB%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88)

概念は、[MSの説明](https://docs.microsoft.com/ja-jp/azure/storage/storage-dotnet-how-to-use-blobs)がわかりやすいです。
![説明](https://docs.microsoft.com/ja-jp/azure/includes/media/storage-blob-concepts-include/blob1.jpg)!

ほかにも、Queue StorageやTable Storageなどがあり、特にTable StorageはNoSQLに放り込むためのjsonの構造化ができたりして。。。すごく面白いです。


# Azure consoleの設定


Azureの画面から、新規のストレージアカウントを作成します。

<img width="689" alt="Storage_-_Microsoft_Azure.png" src="https://qiita-image-store.s3.amazonaws.com/0/113049/992bbab4-cb61-4d9b-2760-697b6214ff25.png">

名前をいれて、あとは大体そのままで大丈夫です。リージョンは東日本を選びました。

<img width="377" alt="ストレージ_アカウントの作成_-_Microsoft_Azure.png" src="https://qiita-image-store.s3.amazonaws.com/0/113049/51e20523-eaa7-99a8-782a-1bad772147c9.png">

作成を押すと、少しまちます。アカウントができたら、アクセスキーを取得しましょう。

<img width="853" alt="gyao2zeolite_-_Microsoft_Azure.png" src="https://qiita-image-store.s3.amazonaws.com/0/113049/0748883e-45ec-f286-7437-ce25b6713314.png">

ストレージアカウントとアクセスキーができました。ここまでいければ、あとはRails側の話になります。


<img width="840" alt="アクセス_キー_-_Microsoft_Azure.png" src="https://qiita-image-store.s3.amazonaws.com/0/113049/d35d0470-c8c0-3a0a-a57e-3363154f4e1a.png">


# Rails側の設定

今回、試しなので新規のRails PJを作成しました。
一行、gemの設定を入れます。


Gemfile

```
gem 'azure-storage'
```

bundle installすれば、すぐに使えるようになります。実際に使うときは、config/environment系に入れ、キーは環境変数で渡すことになりますが、今回はお試しなのでコマンドラインでべた書きします。


コマンドラインのスニペットです。

```
MyMac:AzureStorage btamari$ rails c
Loading development environment (Rails 5.0.0.1)

irb(main):001:0> require "azure/storage"
=> false

# client というオブジェクトを先程のキーで生成
irb(main):002:0>  client = Azure::Storage::Client.create(:storage_account_name => "btamari-test", :storage_access_key => "さっきのAPIキー")
=> #<Azure::Storage::Client:0x007ff94ba3cf18 @ca_file=nil, @options={:storage_account_name=>"btamari", :storage_access_key=>"さっきのAPIキー", :default_endpoints_protocol=>"https", :storage_dns_suffix=>"core.windows.net", :storage_blob_host=>"https://btamari.blob.core.windows.net", :storage_table_host=>"https://btamari.table.core.windows.net", :storage_queue_host=>"https://btamari.queue.core.windows.net", :storage_file_host=>"https://btamari.file.core.windows.net", :use_path_style_uri=>false}, @storage_access_key="さっきのキー", @storage_account_name="btamari", @storage_connection_string=nil, @storage_sas_token=nil, @storage_table_host="https://btamari.table.core.windows.net", @storage_blob_host="https://btamari.blob.core.windows.net", @storage_queue_host="https://btamari.queue.core.windows.net", @agents=nil>

```

ずらずらずらっと出てきました。これで準備完了です。ローカルにproduct_groups_1117-0225.jsonというファイルを置きました。

```
# blobsという名のclientオブジェクトを作成
blobs = client.blob_client

# コンテナの作成。コンテナ名はここで決まります。存在しなければ、新規で作成されます。
container = blobs.create_container("test-container")

# ファイルのアップロード
content = File.open('product_groups_1117-0225.json', 'rb') { |file| file.read }
blobs.create_block_blob(container.name, "product_groups_1117-0225.json", content)

```
テストでは4.5Mbほどのファイルをアップロードしたのですが、体感で20秒くらい時間がかかりました（自宅のCATVの遅い回線)


あとはコマンドで確認できるのですが、それよりも画面で見たほうが良いでしょう。

<img width="1354" alt="test-container_-_Microsoft_Azure.png" src="https://qiita-image-store.s3.amazonaws.com/0/113049/333bbb1e-4f45-8768-8f23-07494ac1e752.png">


```
# List containers
blobs.list_containers()

# List Blobs
blobs.list_blobs(container.name)

# Download a Blob
blob, content = blobs.get_blob(container.name, "image-blob")
File.open("download.png", "wb") {|f| f.write(content)}

# Delete a Blob
blobs.delete_blob(container.name, "image-blob")
```

一応、これで基本的な書き込みはできることがわかりました。今回の開発では、バッチでjsonデータをETLに送るだけなので問題はないのですが、別の使い方だとおそらく速度が遅いので、非同期で動かすとかしないとユーザー側が困る感じですね。