PHPでDropboxAPIを使う
Dropbox API v2 は公式のPHP用sdkが用意されていないので、直接HTTPリクエストを利用します。
⇒cURL関数を使うのがよいでしょう。
事前準備:API用の登録を行う
https://www.dropbox.com/developers
↑ここから「Create your app」→「Dropbox API」で登録します。
登録したら、「generate access token」でアクセストークンを生成してメモしておきます。
【追記】2021/09/30 以降の認証方式
従来の永続的なアクセストークンは廃止されるとのこと。
代わりに、リフレッシュトークンを利用して短期的なアクセストークンを取得して各APIを呼び出す必要があるようです。
(参考)
Migrating App Permissions and Access Tokens
Dropbox API: アプリの権限とアクセス トークンの移行
- アクセストークン取得方法
(1) ブラウザでAUTHORIZATION_CODEを取得する
https://api.dropbox.com/oauth2/authorize?token_access_type=offline&response_type=code&client_id=<APP_KEY>
(2) コマンドでリフレッシュトークンを取得
curl https://api.dropbox.com/oauth2/token \
-d code=<AUTHORIZATION_CODE> \
-d grant_type=authorization_code \
-u <APP_KEY>:<APP_SECRET>
(3) リフレッシュトークンでアクセストークンを取得
curl https://api.dropbox.com/oauth2/token \
-d grant_type=refresh_token \
-d refresh_token=<REFRESH_TOKEN> \
-u <APP_KEY>:<APP_SECRET>
これをコード化すると…
private function getAccessToken()
{
$url = 'https://api.dropboxapi.com/oauth2/token';
$data = [
'grant_type' => 'refresh_token',
'refresh_token' => self::REFRESH_TOKEN,
];
$ch = curl_init();
$options = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => self::APP_KEY . ":" . self::APP_SECRET,
CURLOPT_POSTFIELDS => http_build_query($data)
);
curl_setopt_array($ch, $options);
$res = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$token = '';
if (!curl_errno($ch) && $http_code == "200") {
$res = json_decode($res, true); //連想配列で返す
$token = $res['access_token'];
} else {
print_r("ERROR: Failed to access DropBox via API" . PHP_EOL);
print_r(curl_error($ch) . PHP_EOL);
}
curl_close($ch);
return $token;
}
(4) 取得したアクセストークンを利用
$this->access_token = $this->getAccessToken();
【追記2】チーム向けDropboxの仕様変更
Dropbox Businessのチームプランを利用している場合に限りますが、フォルダツリーが「チームフォルダ」形式から「チームスペース」形式へと順次変更されるようです。
(参考)
DBX Team Files Guide
チーム スペースを使用するチームへの対応ガイド
端的にいうと、チームフォルダへアクセスするにはヘッダーでDropbox-API-Path-Root
を指定する必要があるようです。
指定する値は、アカウント情報から取得できるnamespace_idです。
"root_info": {
".tag": "user",
"home_namespace_id": "3235641",
"root_namespace_id": "3235641"
},
従来どおりチームフォルダへアクセスする場合は、以下のようにヘッダーに追記すればよさそうです。
--header 'Dropbox-API-Path-Root: {".tag": "root", "root": "<root_namespace_id>"}
または
--header 'Dropbox-API-Path-Root: {".tag": "namespace_id", "namespace_id": "<root_namespace_id>"}
これをコード化すると…
private function getRootNameSpace()
{
$url = "https://api.dropboxapi.com/2/users/get_current_account";
$ch = curl_init();
$headers = array(
'Authorization: Bearer ' . $this->accessToken, //取得したアクセストークン
'Content-Type: application/json',
);
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => null, //POSTパラメータ不要
CURLOPT_RETURNTRANSFER => true,
);
curl_setopt_array($ch, $options);
$res = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$root_id = '';
if (!curl_errno($ch) && $http_code == "200") {
$res = json_decode($res, true);
$root_id = $res['root_info']['root_namespace_id'];
} else {
print_r("ERROR: Failed to access DropBox via API" . PHP_EOL);
print_r(curl_error($ch) . PHP_EOL);
}
curl_close($ch);
return $root_id;
}
これを以降のAPIコール時のヘッダーに追加してあげればOKです。
$this->root_namespace_id = $this->getRootNameSpace();
確認:Dropbox API Explorerでテスト
公式にHTTPリクエストのテスト画面があるので、ここで用意されているAPIの一覧やURL、パラメータを確認しておきましょう。
ファイル一覧を取得する
特定フォルダ下のファイル一覧を取得する場合は、
を使います。
オプションでサブフォルダ下も見るかどうかなど指定可能です。
list_folder
で取得し、さらに続きがある場合はlist_folder/continue
で続きを取得することになります。
function getFileList($dirname)
{
$url = "https://api.dropboxapi.com/2/files/list_folder";
$ch = curl_init();
$headers = array(
'Authorization: Bearer ' . $this->access_token, //取得したアクセストークン
'Dropbox-API-Path-Root: {".tag": "root", "root": "' . $this->root_namespace_id . '"}', //チームフォルダへアクセスする場合
'Content-Type: application/json',
);
$post = array(
"path" => "{$dirname}", //対象のディレクトリ
"recursive" => true, //サブフォルダ下も見る
);
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($post),
CURLOPT_RETURNTRANSFER => true,
);
curl_setopt_array($ch, $options);
$res = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$files = array();
if (!curl_errno($ch) && $http_code == "200") {
$res = json_decode($res, true); //連想配列で返す
if ($res["entries"]) {
foreach ($res["entries"] as $index => $content) {
if ($content[".tag"] == "file") {
$files[] = $content;
}
}
}
if ($res["has_more"]) {
//続き読み込み
$morefiles = $this->getFileListRecursive($res["cursor"]);
$files = array_merge($files, $morefiles);
}
} else {
print_r("ERROR: Failed to access DropBox via API" . PHP_EOL);
print_r(curl_error($ch) . PHP_EOL);
}
curl_close($ch);
var_export($files);
}
function getFileListRecursive($cursor)
{
$url = "https://api.dropboxapi.com/2/files/list_folder/continue";
$ch = curl_init();
$headers = array(
'Authorization: Bearer ' . $this->access_token,
'Dropbox-API-Path-Root: {".tag": "root", "root": "' . $this->root_namespace_id . '"}', //チームフォルダへアクセスする場合
'Content-Type: application/json',
);
$post = array(
"cursor" => "{$cursor}", //ファイル取得レスポンスに含まれるカーソルがパラメータ
);
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($post),
CURLOPT_RETURNTRANSFER => true,
);
curl_setopt_array($ch, $options);
$res = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$files = array();
if (!curl_errno($ch) && $http_code == "200") {
$res = json_decode($res, true);
if ($res["entries"]) {
foreach ($res["entries"] as $content) {
if ($content[".tag"] == "file") {
$files[] = $content;
}
}
}
if ($res["has_more"]) {
//再帰的に読み込み
$morefiles = $this->getFileListRecursive($res["cursor"]);
$files = array_merge($files, $morefiles);
}
} else {
print_r("ERROR: Failed to access DropBox via API" . PHP_EOL);
print_r(curl_error($ch) . PHP_EOL);
}
curl_close($ch);
return $files;
}
指定ファイルの共有リンクを取得する
取得したファイルのダウンロード用のリンクが欲しい場合は共有リンクを取得します。
また、共有リンクを発行することもできます。
function getSharedLink($path)
{
$url = "https://api.dropboxapi.com/2/sharing/list_shared_links";
$ch = curl_init();
$headers = array(
'Authorization: Bearer ' . $this->access_token,
'Dropbox-API-Path-Root: {".tag": "root", "root": "' . $this->root_namespace_id . '"}', //チームフォルダへアクセスする場合
'Content-Type: application/json',
);
$post = array(
"path" => "{$path}", //ファイルパス
"direct_only" => true, //ファイルへのアクセスのみ許可
);
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($post),
CURLOPT_RETURNTRANSFER => true,
);
curl_setopt_array($ch, $options);
$res = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$link = "";
if (!curl_errno($ch) && $http_code == "200") {
$res = json_decode($res, true);
if ($res["links"]) {
$links = $res["links"];
$firstlink = $links[0];
$link = $firstlink["url"];
} else {
//なければ共有リンク発行
$link = $this->createSharedLink($path);
}
} else {
print_r("ERROR: Failed to access DropBox via API" . PHP_EOL);
print_r(curl_error($ch) . PHP_EOL);
}
curl_close($ch);
return $link;
}
function createSharedLink($path)
{
$url = "https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings";
$ch = curl_init();
$headers = array(
'Authorization: Bearer ' . $this->access_token,
'Dropbox-API-Path-Root: {".tag": "root", "root": "' . $this->root_namespace_id . '"}', //チームフォルダへアクセスする場合
'Content-Type: application/json',
);
$post = array(
"path" => "{$path}", //ファイルパス
"settings" => array(
"requested_visibility" => array(
".tag" => "public" //公開
),
),
);
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($post),
CURLOPT_RETURNTRANSFER => true,
);
curl_setopt_array($ch, $options);
$res = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$link = "";
if (!curl_errno($ch) && $http_code == "200") {
$res = json_decode($res, true);
if ($res["url"]) {
$link = $res["url"];
} elseif ($res["error"]) {
//既に設定済みなど
$error = $res["error"];
print_r("WARNING: Failed to create shared link [{$path}] - {$error['.tag']}" . PHP_EOL);
}
} else {
print_r("ERROR: Failed to access DropBox via API" . PHP_EOL);
print_r(curl_error($ch) . PHP_EOL);
}
curl_close($ch);
return $link;
}
まとめ
このあたりを組み合わせて、Dropbox上のファイルのダウンロードページをつくったりしました。
ファイルアップロードもできるようにすればストレージをDropboxにしたWEBサービスもつくれそうです。
⇒2019/6/29アップロード編書きました。