Scala番外編「Boxに保存したファイルをBox APIを使ってダウンロードしよう!」
はじめに
みなさんこんにちは、プロダクト開発本部の亀梨です。
普段はXmediaOneというメディアプランニング・広告運用管理・トラッキング・マーケティング分析を行う
統合プラットフォームの開発を担当しています。
Box APIを使う背景・目的
DACはメディアレップです
メディアレップとは、インターネット広告の取引において、広告媒体サイトと広告会社の仲介を行っている事業者のことです。
DACでは数多くの媒体のインターネット広告メニューを取り扱っており、広告媒体サイトから広告枠を、同じく広告会社から広告出稿の案件を預かり、両者にとって最適な条件となるようにマッチングさせる役割を担っています。
DAC AD GUIDE
Boxについて
DACでは各広告媒体のメニュー詳細情報や料金、広告素材を入稿する際の規定等を記した資料(以下、媒体資料)を用意しています。
広告代理店担当者様やDACのプランナーが出稿する広告メニューを検討する際に使います。
この媒体資料はDAC社内で「Box」というファイル共有サービスに格納・管理しています。
Box – セキュアなファイル共有、ストレージ、コラボレーション
Box APIについて
Boxは外部サービスとの連携ができるようにするAPIを提供しています。
Box Developer Portal
XmediaOneでのBox APIの利用
XmediaOneは広告代理店担当者様やDACのプランナーがどの媒体に広告を出稿するかをプランニングする機能となっており、
その中でDACが保有している媒体資料を社内外に広く公開するために、Box APIを使って資料をダウンロードできる仕組みを構築しました。
今回はXmediaOneとBoxAPIを連携させる事例を紹介したいと思います。
前提
XmediaOneはScala言語で開発しています。そしてビルドツールはsbtを使っています。
また今回Box APIを利用するにあたってはBoxが提供しているJavaのSDKを使います(詳しくは後述)。
開発環境
- Scala 2.11.8
- sbt 0.13.13
- Box Java SDK 2.24.0
試したこと
Boxの事前設定
管理者アカウントで管理コンソールにログインし、API用のユーザーアカウント(以下、閲覧ユーザー)を作成
APIにリクエストを投げる際に必要なユーザーアカウントを作成します。
詳細はこちらより確認してください。
Boxのファイル閲覧画面にログインし、ダウンロードしたい対象のファイルを格納しているディレクトリに閲覧ユーザーをコラボレータとして追加
閲覧ユーザーでBoxの開発者コンソールを開き、必要な設定を行う
1. Boxにログインした状態で、Developerコンソールを開く
開発者コンソールのURLは https://xxxxx.ent.box.com/developers/console →xxxxxの部分が会社ごとに違う
2. アプリを新規作成する
外部システム(今回で言うXmediaOne)とBox APIを連携させるために、Boxでは連携用の”アプリ”を作成する必要があります。
↑の画面中央の「アプリの新規作成」をクリックし新しいBoxアプリを作成する画面に移ります。
そして次の画面で、アプリの種別を選択します。今回のケースのように既にあるBoxのファイルに対してAPI経由で操作を行う場合は
「企業統合」を選択して「次へ」ボタンをクリックします。
3. 認証方法を選択する
今回のように既存のプラットフォーム内のサーバー上でAPIの認証・リクエストを行う場合には、
「JWTを使用したOAuth 2.0 (サーバー認証)」を選択します。
4. アプリの作成完了
アプリの作成が完了すると以下の画面になりますので、中央にある「アプリの表示」ボタンをクリックします。
5. アプリの「構成」ページで必要な設定を行う
以下の画面よりファイルダウンロードができるようにするための設定を行います。
詳細は公式ドキュメントの「JWTアプリケーションの設定」に記載がありますが、正直これ分かりづらいです^^;
なのでかいつまんでご説明します。ファイルダウンロードをするのに変更が必要な項目としては、
- アプリケーションアクセス
- Enterpriseを選択
- アプリケーションスコープ→ファイルダウンロードに必要な最小スコープとして以下にチェックを付ける
-
- Boxに格納されているすべてのファイルとフォルダの読み取り
- Boxに格納されているすべてのファイルとフォルダの読み取りと書き込み
- ユーザーを管理
-
- 高度な機能
- ユーザーとして操作を実行 をOnにする
- ユーザーアクセストークンを生成 をOnにする
ここまでの設定を行ったら、画面右上の「変更を保存」ボタンをクリックします。
そして次に、「公開キーの追加と管理」項目の「公開/秘密キーペアを生成」をクリックします。
すると、上記で設定した構成を反映したJSONファイルがダウンロードされます。
このJSONファイルにはAPIを使うのに必要なユーザー情報や秘密キーが保存されています。再ダウンロードができないため、慎重に扱ってください。
ここまでで開発者コンソールでの設定は完了です。
管理コンソールで作成したアプリの登録、承認を行う
管理者アカウントで管理コンソールにアクセスし、以下の手順を使用して、アプリケーションへのアクセス権限を付与します。
- 管理コンソールのBusiness設定を開きます。
- ページ上部のナビゲーションの[アプリ]リンクをクリックします。
- [カスタムアプリケーション]セクションまで下にスクロールし、[新しいアプリケーションを承認**]ボタンをクリックします。
- APIキーを求められたら、最初の手順で作成したJWTアプリケーションのクライアントIDを入力します。
クライアントIDは先ほどの開発者コンソールのアプリの構成ページ内「OAuth 2.0資格情報」にあるクライアントIDです。
Scalaでのダウンロード処理の実装
はい、ちょっと事前設定の説明が長くなってしまいましたが、ようやく実装に入ります。
SDKのインストール
先にも書きましたが、Boxは複数の言語でSDKを提供しています。今回はScalaでの実装となるため、
Javaで提供されているライブラリ「Box Java SDK」を使用します。
Box Java SDK
build.sbtに以下の様に依存関係を記載して利用します。
1 |
libraryDependencies += "com.box" % "box-java-sdk" % "2.24.0" |
Scalaの実装コード
Box APIにアクセスする手順としては
- 作成したアプリの構成を設定ファイルから読み込み
- 構成を元にAPIの操作を行うためのオブジェクトを作成
- ファイルを操作するAPIアクセスを実行
となります。まずは実装コードの全体を見ていきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import java.io.{FileOutputStream, FileReader} import com.box.sdk._ // Boxアプリの構成ファイルをBox Configオブジェクトに読み込む val reader = new FileReader("YOUR CONFIG FILE PATH") val boxConfig = BoxConfig.readFrom(reader) // キャッシュ情報を設定する val MAX_CACHE_ENTRIES = 100 val accessTokenCache = new InMemoryLRUAccessTokenCache(MAX_CACHE_ENTRIES) // BoxのXmedaiOneアプリのエンタープライズコネクションオブジェクトを生成する val USER_ID = 'YOUR APPLICATION USER ID' val api = new BoxDeveloperEditionAPIConnection(USER_ID, DeveloperEditionEntityType.USER, boxConfig, accessTokenCache) // Boxファイルダウンロード val boxFileId = 'BOX FILE ID' val file = new BoxFile(api, boxFileId.toString) val info = file.getInfo() val stream = new FileOutputStream(info.getName()) file.download(stream) stream.close() |
では手順ごとにコードを細かく見ていきましょう。
手順1: 構成の出力
先ほど事前設定でダウンロードしたファイルをプロジェクト内の任意の場所に格納しておきます。
そしてそのファイルに記載されたアプリケーションの情報やプライベートキーの構成オブジェクトを作成します。
1 2 3 4 5 6 |
import java.io.{FileOutputStream, FileReader} import com.box.sdk._ // Boxアプリの構成ファイルをBox Configオブジェクトに読み込む val reader = new FileReader("YOUR CONFIG FILE PATH") val boxConfig = BoxConfig.readFrom(reader) |
手順2: 新規Box SDKクライアントの作成
このクライアントを使うとBox内のファイルに呼び出しができます。
1 2 3 4 5 6 7 |
// キャッシュ情報を設定する val MAX_CACHE_ENTRIES = 100 val accessTokenCache = new InMemoryLRUAccessTokenCache(MAX_CACHE_ENTRIES) // BoxのXmedaiOneアプリのエンタープライズコネクションオブジェクトを生成する val USER_ID = 'YOUR APPLICATION USER ID' val api = new BoxDeveloperEditionAPIConnection(USER_ID, DeveloperEditionEntityType.USER, boxConfig, accessTokenCache) |
上記のユーザーIDは閲覧ユーザのIDで、事前設定で作成したアプリの開発者コンソールで確認することができます。
XmediaOneでは事前にファイルIDを登録する機能を作っており、そのファイルをJSONでAPIにGETリクエストする形をとっています。
手順3: ファイルのダウンロード
いよいよファイルのダウンロードです。
ダウンロードするにはファイルのIDが必要になります。開発者コンソールではなく通常のBoxページでダウンロードしたいファイルIDを確認します。
はい、実装コードは以下となります。
1 2 3 4 5 6 7 8 |
// Boxファイルダウンロード val boxFileId = 'BOX FILE ID' val file = new BoxFile(api, boxFileId.toString) val info = file.getInfo() val stream = new FileOutputStream(info.getName()) file.download(stream) stream.close() |
はい、以上が実装コードとなります。ちなみにBox APIでの様々な操作の具体的な実装方法についてはGitHubのページに詳しく掲載されています。
これでファイルがダウンロードできましたーめでたしめでたしー。。。
エラーの解消
と思いきや、このBox APIの実装には解消しなければいけないエラーがあります。
上記のコードを実行すると、
1 |
Unlimited Strength Jurisdiction Policy Files are required but not installed. |
というエラーに遭遇します。これはJavaのセキュリティポリシーを更新しなければいけないということらしいです。
手順としては、
- オラクルのWebサイトより必要なファイル US_export_policy.jar と local_policy.jar をダウンロード
- ダウンロードしたファイルを、アプリケーションサーバーにインストールしてあるJavaの該当パス (JAVA_HOME)/jre/lib/security にコピー(上書き)
となります。これを行うことでエラーが解消され正常にAPIでファイル操作が可能となります。
このエラー解消にはこちらの記事が参考になりました。
まとめ
今回はBox APIという外部APIを使うにあたり、認証に関する事前設定・動作検証に多くの時間を費やしました。
実装コード自体は単純なのですが、このAPIは公式のドキュメントの文章が翻訳のせいなのか少々難解で読み解くのに非常に苦労しました。
なおBoxでは開発者フォーラム(英語)があり、なにか不明点が出た際はこちらに質問を投げるとBoxの中の人が1営業日程度で回答を返してくれます。割と親切です。
今回の教訓としては、「外部APIと連携させる場合は事前に入念な動作検証をしておけ!」です。
APIだからといって安易に導入すると苦労するぞということを学びましたw。
はい、ということで少し長くなりましたが、Box APIを使ってBoxファイルをダウンロードする方法を紹介させていただきました。
またなにか面白い事例等がありましたらこの場で共有させていただきます。それではー。

関連記事
-
-
ゼロからAngularでSPAを作ってみた(3) CI: 継続的インテグレーション編
前回までのおさらいと今回やること 前々回(はじめてのアプリ編)と前回(デプロイ・公開編)で、作成した Angular のチャットアプリを Web に公開するところまでいきました。 でも、デプロイするのに、毎回決まったコマンドを打つのって面倒ですよね。 今回は GitHub でソースコードを管理して、 …
-
-
ナイーブベイズで羽生さんと羽生くんを分類してみた
はじめに こんにちは。システム開発部の中村です。 機械学習についての理解を促進するため、 データから分類モデルを自動で構築する古典的な方法である、 ナイーブベイズ分類器を実装してみました。 最近はCloudVisionAPIなど専ら画像解析が流行っていますが、 自分のような初学者には敷居が高そうだっ …
-
-
【小ネタ】Javascriptのconsoleオブジェクトをもっと便利に使う方法
すごく便利なconsoleオブジェクトですが、ブラウザによってサポートされているメソッドが なかったり、そもそもconsoleオブジェクトが使えなかったりと、たまに不便だったりします。 そんなときによく使う便利なコード。 [code language=”javascript” …
-
-
意外と知らないかも? Chrome DevTools の機能10選
みんな使っている Chrome DevTools。 Web開発やトラブルシューティングには必須ですが、便利な機能を知らないで使っている人がいたり、Web で使い方を調べても古い情報だったりすることがあるので、部内で Chrome DevTools についての勉強会を開催しました。 ここでは、その中か …
-
-
Scala実践「Either型を使ってimmutable(不変)なコードを書こう!」
はじめに みなさんこんにちは、プロダクト開発本部の亀梨です。 普段はXmediaOneというメディアプランニング・広告運用管理・トラッキング・マーケティング分析を行う 統合プラットフォームの開発を担当しています。 Scalaでイケてるコードを書きたい! 背景 わたくしはDACに入社してからScala …
-
-
クラウド電話API “Twilio”で起こされてみた
どうも、開発部のクラヴマガです。 弊社サービスも最近はAWSの様なクラウド環境でサービスを構築することが多くなりました。 そこで問題になるのが、障害などによる深夜対応・・・。 データセンターに物理サーバをおいていた頃は、データセンターから障害発生時に 電話連絡をもらっていたのですが、クラウド環境では …
-
-
初心者がRailsで開発 – deviseでユーザー認証設定 –
こんにちは、2年目のYukaです。 開発部所属でありながら実は、、 実際に自分で手を動かして開発する機会がなかなかありませんでした。。 しかしついに、、、 開発初心者がRailsでWebアプリの開発に挑戦します!! 今回のゴールは社内でも使用しているGoogleアカウントで簡単にログインができるよう …
-
-
kubernetes の全ノード上で同じコンテナを動かす
今回は、kubernetes上で同一コンテナを全ノードで動かす方法を紹介したいと思います。kubernetes自体の起動方法はここでは割愛します。 はじめに 以前、CoreOSのFleet上でmackerel-agentを動かすということを行いました。今回は、kubernetes上で同じようにクラス …
-
-
Angular.jsのvalueとfactoryの違いを考える
次のようなHTMLがあったとする。 [code language=”html”] <!doctype html> <html lang="jp" ng-app="App"> <head> <me …
-
-
ゼロからAngularでSPAを作ってみた(2) デプロイ・公開編
前回のおさらいと今回やること 前回(はじめてのアプリ編)では、Angular で簡単なチャットアプリを作るところまでやりました。ディレクトリ構成については説明できていなかったのですが、次のようになっています。(主なディレクトリとファイルのみ抜粋) + dist (ビルド・コンパイル後のファイルのディ …