boxのリンクをGoogleドライブのリンクに変換する方法
boxからGoogleドライブへ移行をした際にNotionにまとめていたファイルのリンクを置き換える必要があり、APIを使って変換した話
めったにやらないでしょうが、APIの使い方が勉強になったのでまとめます
なおスピード重視だったのでプログラムにしたのは必要最低限で手作業の部分が多いです
処理の流れ
Notionに張られていたのはhttps://app.box.com/s/xxxxxxx
という形式の共有リンクだった
これを一度フォルダ・ファイル名に変換し
移行先の共有ドライブ内でフォルダ・ファイル名で検索し
Googleドライブのリンクを生成する
Box API
アクセストークンの生成
このチュートリアルを使います
手順に従っていくとBoxのAPI仕様を理解せずともAPIコールに必要なアクセストークンが取得できます
Boxの共有リンクをファイルパスに変換する
「共有リンクのウェブリンクを検索」APIを使います
知っておくべきAPI仕様はこれだけです
メソッド | URL | ヘッダー(boxapi) | ヘッダー(Authorization) |
---|---|---|---|
GET | https://api.box.com/2.0/shared_items | shared_link=[link] | Bearer [アクセストークン] |
他のAPIについてはAPIリファレンスから探すのが正攻法だと思いますが
私は先のチュートリアルで生成したPostmannプロジェクトでそれらしいリクエストを実際に送って確認しました
(Boxをあまり使ったことがなく「共有リンク」や「ウェブリンク」などの言葉がわからずリファレンスから探よりこっちが速かった)
この仕様をもとにURLをファイルパスに変換する簡単なスクリプトを実装
/**
* Boxの共有リンクをファイルパスに変換する
*
* 環境変数
* BOX_TOKEN
*/
import axios from 'axios';
const sharedLinks = [
// ここにURLをハードコーディング
];
for (const sharedLink of sharedLinks) {
if (!sharedLink) {
console.log('');
continue;
}
try {
const result = await axios.request({
method: 'get',
maxBodyLength: Infinity,
url: 'https://api.box.com/2.0/shared_items',
headers: {
boxapi: `shared_link=${sharedLink}`,
Authorization: `Bearer ${process.env.BOX_TOKEN}`,
},
});
console.log(result.data.name);
} catch (error) {
console.log('error');
}
}
これでコンソールには大量のファイルパスが出力される
URLとファイルパスの対応表を適当な表計算ソフトでまとめておきます
BoxのURL | ファイルパス |
---|---|
https://app.box.com/s/xxxxxxx | path/to/file |
Google Drive API
パスが分かったのでこれをもとにGoogleドライブのURLを生成していきます
OAuthの仕組み
残念ながらBoxのようなチュートリアルはGoogleになかったので手動でアクセストークンを発行します
これに当たって簡単にOAuthによる認証フローをおさらい
アクセストークンの生成
- Google CloudのコンソールでGoogle Drive APIを有効化します
-
OAuth 同意画面を作成します
- 承認済みドメインは適当に
example.com
としておきます - スコープに
drive.metadata.readonly
を追加します
- 承認済みドメインは適当に
-
OAuthクライアントIDを作成します
- アプリケーションの種類はウェブアプリケーションを選択
- 承認済みのリダイレクトURIに
https://oauth2.example.com/code
を指定 - ここで作ったクライアントのIDとシークレットを以降使用します
- 以下のURLをブラウザのアドレスバーに打ち込んでアクセス
https://accounts.google.com/o/oauth2/v2/auth
?scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly
&access_type=offline
&include_granted_scopes=true
&response_type=code
&state=state_parameter_passthrough_value
&redirect_uri=https%3A//oauth2.example.com/code
&client_id=[クライアントID]
- Googleにアクセス許可を与えていいか聞かれるので許可
- ブラウザのアドレスバーが以下のようなURLになる(はず)
https://oauth2.example.com/code
?state=state_parameter_passthrough_value
&code=[認証コード]
&scope=[許可されたスコープ]
- Postmanを使って認証コードをアクセストークンと交換
POST https://oauth2.googleapis.com/token
bodyはx-www-form-urlencodedで
Key | Value |
---|---|
code | 認証コード |
client_id | クライアントID |
client_secret | クライアントシークレット |
redirect_uri | https://oauth2.example.com/code |
grant_type | authorization_code |
パスをもとにファイルを検索する
以下のAPIを利用しました
パスをもとにフォルダ階層を探していってもよかったんですが
実装がめんどくさかったのでファイル名で検索しています
(後でこれが役に立ちます)
このために表計算ソフトでファイル名を抜いてきます
BoxのURL | ファイルパス | ファイル名 |
---|---|---|
https://app.box.com/s/xxxxxxx | path/to/file | =SUBSTITUTE(RIGHT(SUBSTITUTE(B2,"/",REPT("/",256)),256),"/","") |
そして以下のコードでファイルのIDを列挙します
DRIVE_IDには共有ドライブのIDを指定します
このIDはdrives.list APIで確認できます
/**
* ファイルパスからGoogle DriveのファイルIDを検索する
*
* 環境変数
* DRIVE_ID
* DRIVE_TOKEN
*/
import axios from 'axios';
const filenames = [
// ここにファイル名をハードコーディング
];
for (const filename of filenames) {
if (!filename) {
console.log('');
continue;
}
try {
const result = await axios.request({
method: 'get',
maxBodyLength: Infinity,
headers: {
Authorization: `Bearer ${process.env.DRIVE_TOKEN}`,
},
url:
`https://www.googleapis.com/drive/v3/files` +
`?driveId=${process.env.DRIVE_ID}` +
`&corpora=drive` +
`&includeItemsFromAllDrives=true` +
`&includeTeamDriveItems=true` +
`&supportsAllDrives=true` +
`&q=${encodeURIComponent(`name ='${filename}' and trashed = false`)}`,
});
console.log(result.data.files.map((e) => e.id).join(','));
} catch (error) {
console.log('error');
}
}
GoogleドライブのURLは以下のフォーマットなので表計算ソフトでURLに変換します
https://drive.google.com/file/d/[ファイルID]
BoxのURL | ファイルパス | ファイル名 | URL |
---|---|---|---|
https://app.box.com/s/xxxxxxx | path/to/file | (省略) | ="https://drive.google.com/file/d/"&C2 |
検索することでファイルの重複チェックにも
今回の方式で結果的にファイルの重複チェックも行えました
Googleドライブはショートカットを作成できるので、別の目的でフォルダにまとめたい時はコピーではなくショートカットを使うといいですね
Discussion