新手 Google 驱动 API (PHP) 困惑 - guide/library 有什么用?
Newbie Google Drive API (PHP) confusion - what guide/library to use?
我有一个移动网站 m.example.com - 来自 phone 我希望访问者从 Google 驱动器中选择一个文件,并将其发送到托管 m.example.com.本质上是在桌面上模拟简单的 <input type="file">
文件上传。
据我了解,工作流程如下:
1) 用户使用选择器选择文件,选择器将所选文件的元数据发送到我的网站客户端(即 phone/tablet 上的 HTML/Javascript 运行)
2) 我通过 ajax 或只是一个表单隐藏字段
将其发送到我的服务器
3) 我的服务器向 Google API 发出请求以获取文件,然后将其存储在服务器的文件系统中
所以我需要帮助:
a) 上述步骤是否正确,是否有任何其他方法可以做到这一点,或者甚至是我可以使用的服务将允许我的站点用户从几个云存储提供商之一选择他们的文件?
a) 假设我的步骤是正确的并且这是唯一的方法,我被困在 3) 部分 - 服务器与 API.
对话
到目前为止,我已经按照此处设置了选择器 - Google picker auth popup is being blocked 并获得了文件 URL。我还没有完成 2),我只是暂时手动将文件 URL 放入我的下载脚本中。
我正在使用 PHP,我想下载到我的服务器的文件可以是 public 或私有的,这取决于最终用户。
我迷失在 API 文档中(如手册页,而不是 google 文档)并且对 https://developers.google.com/api-client-library/php/start/get_started (call this API docs)and https://developers.google.com/drive/web/quickstart/quickstart-php(称其为 Drive 文档)感到困惑 - 这些是两个不同的 APIs?
我点击了 API 文档中的链接并从这里安装了客户端:https://github.com/google/google-api-php-client,但是当在 Drive 文档上尝试 "Step 3: Set up the sample" 时,我收到很多错误,例如文件不正确发现,class 不是源泉等等,所以这让我觉得这里记录的是两个不同的 APIs/Clients - 有人能给我指出正确的入门方向吗?
更新
我已经针对从此 https://developers.google.com/api-client-library/php/start/get_started
链接的 github 重新安装了 PHP 客户端
这是它的样子:
我 运行 示例目录中的 simplefileupload.php - 第一次工作,只需要输入我的项目详细信息
因此转到 https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample 并在 google-api 的根目录中创建了 drive_rest_api_step_3.php(如屏幕截图所示)
得到Fatal error: require_once(): Failed opening required 'src/Google_Client.php' (include_path='.:/usr/local/lib/php') in /path/to/google-api/drive_rest_api_step_3.php on line 5
图书馆没有Google_Client.php,但是有src/Google/Client。php 所以我编辑 require_once 来使用它。
现在获取 Failed opening required 'src/contrib/Google_DriveService.php'
- 再次搜索该文件没有结果,但是有 src/Google/Service/Drive.php, 所以编辑示例以使用它:
要求(在 https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample 上)是:
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_DriveService.php';
现在:
require_once 'src/Google/Client.php';
require_once 'src/Google/Service/Drive.php';
现在 Fatal error: Class 'Google_Service' not found in /path/to/google-api/src/Google/Service/Drive.php on line 32
所以这就是我认为这两套指南存在问题的原因,要么它们使用不同的库,要么 https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample 已过时,尽管上次更新时间为 2015 年 3 月 30 日。
您说得对,驱动器快速入门指南已过时,它指的是 Google 的 PHP 客户端 API 库的旧版本 Google 代码,而不是 GitHub 上的新代码。因此,快速入门指南不适用于您下载的 PHP 客户端库。此外,快速入门指南代码旨在以 PHP command-line 模式而不是在服务器上执行。
为了回答这个问题,我输入了一些 sub-answers:
- 如何使用 PHP 客户端库
- 如何使用 Google 选取器选取文件并将文件放到服务器上
将 Google PHP 客户端库与 Google 驱动器一起使用 API
试试这个页面:https://developers.google.com/api-client-library/php/auth/web-app 其中有一个示例显示如何使用 new [=126= 列出用户 Google 驱动器上的文件] 库,包括整个 OAuth 程序。
不幸的是,即使这样也有点过时(包含路径已过时,现在已弃用)。因此(为了 Whosebug 的完整性)这里有一些代码。我在我的 Web 服务器根目录中使用了一个子目录 drivetest;根据需要更改 URL。
请注意,您需要在 Google 的 Developer Console 中获取 "Web applications" 的客户端 ID,然后下载 JSON(替换 client_secrets.json
根据需要编写代码)。
drivetest/quickstart.php
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$drive_service = new Google_Service_Drive($client);
$files_list = $drive_service->files->listFiles(array())->getItems();
echo json_encode($files_list);
} else {
$redirect_uri = 'http://localhost/drivetest/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
drivetest/oauth2callback.php
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://localhost/drivetest/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://localhost/drivetest/quickstart.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
使用 Google 文件选择器选择文件
对于您的用例,您最好使用 Google 选择器 https://developers.google.com/picker/docs/,它为您实现整个 browse-and-select-file 事情,并且只为文件提供一个 ID。所需步骤摘要:
- 获取访问令牌(身份验证)
- 使用选择器让用户选择文件
- 使用选择器返回的文件 ID 进行下载 URL
- 从下载中下载文件 URL
我们可以通过两种方式做到这一点(client-side 或 server-side):
方法一:Client-side
使用此方法,步骤 1 - 3 在 Javascript 中完成,而在 PHP 中仅完成步骤 4。使用这种方法,我们甚至不需要 PHP 客户端库!
这是一个示例(改编自上面 link 和 http://webdevrefinery.com/forums/topic/12931-dropbox-google-drive-file-pickers/ 中的示例代码):
picker.html
此文件在页面加载时启动文件选择器并将 URL 放入表单中。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = '';
// The Client ID obtained from the Google Developers Console. Replace with your own Client ID.
var clientId = ""
// Replace with your own App ID. (Its the first number in your Client ID)
var appId = ""
// Scope to use to access user's Drive items.
var scope = ['https://www.googleapis.com/auth/drive'];
var pickerApiLoaded = false;
var oauthToken;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
//view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
//.enableFeature(google.picker.Feature.NAV_HIDDEN)
//.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
gapi.client.load('drive', 'v2', function() {
var request = gapi.client.drive.files.get({
fileId: fileId
});
request.execute(processFile);
});
}
}
function processFile(file) {
var token = gapi.auth.getToken();
// console.log(file);
// console.log(token);
document.getElementById("fileurl").value = file.downloadUrl+"&access_token="+token.access_token;
}
</script>
</head>
<body>
<form action="submit.php" method="post">
<label for="fileurl">File Download URL</label><input type="text" name="fileurl" id="fileurl">
<input type="submit">
</form>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
</html>
然后我们将表单提交到 PHP 脚本以在服务器上下载文件。这里的技巧是我们还需要将访问令牌从客户端传递到服务器,因为用户未在服务器端进行身份验证。令人惊讶的是,您可以简单地附加 access_token
参数来验证文件的下载,如上所示。
submit.php
使用 file_get_contents
或 CURL,具体取决于您的服务器支持的内容。不过需要 HTTPS 支持才能正常工作。
<?php
$filename = 'temp.jpg';
$ch = curl_init($_POST['fileurl']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Should verify in production!
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
//echo 'Curl error: ' . curl_error($ch);
curl_close($ch);
file_put_contents($filename, $data);
?>
更正式的方式(按照https://developers.google.com/drive/web/manage-downloads#alternate_method_using_downloadurl) is to send the authorization token separately using the Authorization
header. Modify the Javascript above to send the download URL and token separately, then use something like the code below instead. If you want to use file_get_contents
, see PHP file_get_contents() and headers关于如何发送自定义headers。注意你需要有Bearer
字在令牌之前!
<?php
$filename = 'temp.jpg';
$ch = curl_init($_POST['fileurl']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$_POST['authtoken']));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
echo 'Curl error: ' . curl_error($ch);
curl_close($ch);
file_put_contents($filename, $data);
?>
方法二:Server-side(使用PHP)
使用此方法,在PHP完成第1、3、4步,Javascript只完成第2步。
quickstart.php
此页面检查 session 中是否有访问令牌,如果没有,它将重定向用户以进行身份验证。如果有,它会显示选择器和表单。在选择器 Javascript 代码中,注意使用的 oAuthToken 是通过 PHP 从服务器获取的!资料来源:Use Google Picker without logging in with Google account (with OAuth)。然后表单向此页面提交 POST 请求并下载文件。
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
// Ref: https://developers.google.com/drive/v2/reference/files/get
function downloadFile($service, $file) {
$downloadUrl = $file->getDownloadUrl();
if ($downloadUrl) {
$request = new Google_Http_Request($downloadUrl, 'GET', null, null);
$httpRequest = $service->getClient()->getAuth()->authenticatedRequest($request);
if ($httpRequest->getResponseHttpCode() == 200) {
return $httpRequest->getResponseBody();
} else {
// An error occurred.
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
if (isset($_POST['fileid'])){
$drive_service = new Google_Service_Drive($client);
$file = $drive_service->files->get($_POST['fileid']);
$data = downloadFile($drive_service, $file);
file_put_contents('temp.jpg', $data);
echo "file uploaded";
exit();
}
} else {
$redirect_uri = 'http://localhost/drivepicker-php/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
exit();
}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = '';
// Replace with your own App ID. (Its the first number in your Client ID)
var appId = ""
var pickerApiLoaded = false;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
// Create and render a Picker object
function createPicker() {
if (pickerApiLoaded) {
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
//view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
//.enableFeature(google.picker.Feature.NAV_HIDDEN)
//.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken('<?= json_decode($client->getAccessToken())->access_token; ?>')
.addView(view)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
document.getElementById("fileid").value = fileId;
}
}
</script>
</head>
<body>
<form action="quickstart.php" method="post">
<label for="fileid">File ID</label><input type="text" name="fileid" id="fileid">
<input type="submit">
</form>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
</html>
oauth2callback.php
OAuth 回调的帮助文件。
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://localhost/drivepicker-php/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_READONLY);
if (!isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://localhost/drivepicker-php/quickstart.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
我有一个移动网站 m.example.com - 来自 phone 我希望访问者从 Google 驱动器中选择一个文件,并将其发送到托管 m.example.com.本质上是在桌面上模拟简单的 <input type="file">
文件上传。
据我了解,工作流程如下:
1) 用户使用选择器选择文件,选择器将所选文件的元数据发送到我的网站客户端(即 phone/tablet 上的 HTML/Javascript 运行)
2) 我通过 ajax 或只是一个表单隐藏字段
将其发送到我的服务器3) 我的服务器向 Google API 发出请求以获取文件,然后将其存储在服务器的文件系统中
所以我需要帮助:
a) 上述步骤是否正确,是否有任何其他方法可以做到这一点,或者甚至是我可以使用的服务将允许我的站点用户从几个云存储提供商之一选择他们的文件?
a) 假设我的步骤是正确的并且这是唯一的方法,我被困在 3) 部分 - 服务器与 API.
对话到目前为止,我已经按照此处设置了选择器 - Google picker auth popup is being blocked 并获得了文件 URL。我还没有完成 2),我只是暂时手动将文件 URL 放入我的下载脚本中。
我正在使用 PHP,我想下载到我的服务器的文件可以是 public 或私有的,这取决于最终用户。
我迷失在 API 文档中(如手册页,而不是 google 文档)并且对 https://developers.google.com/api-client-library/php/start/get_started (call this API docs)and https://developers.google.com/drive/web/quickstart/quickstart-php(称其为 Drive 文档)感到困惑 - 这些是两个不同的 APIs?
我点击了 API 文档中的链接并从这里安装了客户端:https://github.com/google/google-api-php-client,但是当在 Drive 文档上尝试 "Step 3: Set up the sample" 时,我收到很多错误,例如文件不正确发现,class 不是源泉等等,所以这让我觉得这里记录的是两个不同的 APIs/Clients - 有人能给我指出正确的入门方向吗?
更新
我已经针对从此 https://developers.google.com/api-client-library/php/start/get_started
链接的 github 重新安装了 PHP 客户端这是它的样子:
我 运行 示例目录中的 simplefileupload.php - 第一次工作,只需要输入我的项目详细信息
因此转到 https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample 并在 google-api 的根目录中创建了 drive_rest_api_step_3.php(如屏幕截图所示)
得到Fatal error: require_once(): Failed opening required 'src/Google_Client.php' (include_path='.:/usr/local/lib/php') in /path/to/google-api/drive_rest_api_step_3.php on line 5
图书馆没有Google_Client.php,但是有src/Google/Client。php 所以我编辑 require_once 来使用它。
现在获取 Failed opening required 'src/contrib/Google_DriveService.php'
- 再次搜索该文件没有结果,但是有 src/Google/Service/Drive.php, 所以编辑示例以使用它:
要求(在 https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample 上)是:
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_DriveService.php';
现在:
require_once 'src/Google/Client.php';
require_once 'src/Google/Service/Drive.php';
现在 Fatal error: Class 'Google_Service' not found in /path/to/google-api/src/Google/Service/Drive.php on line 32
所以这就是我认为这两套指南存在问题的原因,要么它们使用不同的库,要么 https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample 已过时,尽管上次更新时间为 2015 年 3 月 30 日。
您说得对,驱动器快速入门指南已过时,它指的是 Google 的 PHP 客户端 API 库的旧版本 Google 代码,而不是 GitHub 上的新代码。因此,快速入门指南不适用于您下载的 PHP 客户端库。此外,快速入门指南代码旨在以 PHP command-line 模式而不是在服务器上执行。
为了回答这个问题,我输入了一些 sub-answers:
- 如何使用 PHP 客户端库
- 如何使用 Google 选取器选取文件并将文件放到服务器上
将 Google PHP 客户端库与 Google 驱动器一起使用 API
试试这个页面:https://developers.google.com/api-client-library/php/auth/web-app 其中有一个示例显示如何使用 new [=126= 列出用户 Google 驱动器上的文件] 库,包括整个 OAuth 程序。
不幸的是,即使这样也有点过时(包含路径已过时,现在已弃用)。因此(为了 Whosebug 的完整性)这里有一些代码。我在我的 Web 服务器根目录中使用了一个子目录 drivetest;根据需要更改 URL。
请注意,您需要在 Google 的 Developer Console 中获取 "Web applications" 的客户端 ID,然后下载 JSON(替换 client_secrets.json
根据需要编写代码)。
drivetest/quickstart.php
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$drive_service = new Google_Service_Drive($client);
$files_list = $drive_service->files->listFiles(array())->getItems();
echo json_encode($files_list);
} else {
$redirect_uri = 'http://localhost/drivetest/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
drivetest/oauth2callback.php
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://localhost/drivetest/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://localhost/drivetest/quickstart.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
使用 Google 文件选择器选择文件
对于您的用例,您最好使用 Google 选择器 https://developers.google.com/picker/docs/,它为您实现整个 browse-and-select-file 事情,并且只为文件提供一个 ID。所需步骤摘要:
- 获取访问令牌(身份验证)
- 使用选择器让用户选择文件
- 使用选择器返回的文件 ID 进行下载 URL
- 从下载中下载文件 URL
我们可以通过两种方式做到这一点(client-side 或 server-side):
方法一:Client-side
使用此方法,步骤 1 - 3 在 Javascript 中完成,而在 PHP 中仅完成步骤 4。使用这种方法,我们甚至不需要 PHP 客户端库!
这是一个示例(改编自上面 link 和 http://webdevrefinery.com/forums/topic/12931-dropbox-google-drive-file-pickers/ 中的示例代码):
picker.html
此文件在页面加载时启动文件选择器并将 URL 放入表单中。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = '';
// The Client ID obtained from the Google Developers Console. Replace with your own Client ID.
var clientId = ""
// Replace with your own App ID. (Its the first number in your Client ID)
var appId = ""
// Scope to use to access user's Drive items.
var scope = ['https://www.googleapis.com/auth/drive'];
var pickerApiLoaded = false;
var oauthToken;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
//view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
//.enableFeature(google.picker.Feature.NAV_HIDDEN)
//.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
gapi.client.load('drive', 'v2', function() {
var request = gapi.client.drive.files.get({
fileId: fileId
});
request.execute(processFile);
});
}
}
function processFile(file) {
var token = gapi.auth.getToken();
// console.log(file);
// console.log(token);
document.getElementById("fileurl").value = file.downloadUrl+"&access_token="+token.access_token;
}
</script>
</head>
<body>
<form action="submit.php" method="post">
<label for="fileurl">File Download URL</label><input type="text" name="fileurl" id="fileurl">
<input type="submit">
</form>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
</html>
然后我们将表单提交到 PHP 脚本以在服务器上下载文件。这里的技巧是我们还需要将访问令牌从客户端传递到服务器,因为用户未在服务器端进行身份验证。令人惊讶的是,您可以简单地附加 access_token
参数来验证文件的下载,如上所示。
submit.php
使用 file_get_contents
或 CURL,具体取决于您的服务器支持的内容。不过需要 HTTPS 支持才能正常工作。
<?php
$filename = 'temp.jpg';
$ch = curl_init($_POST['fileurl']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Should verify in production!
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
//echo 'Curl error: ' . curl_error($ch);
curl_close($ch);
file_put_contents($filename, $data);
?>
更正式的方式(按照https://developers.google.com/drive/web/manage-downloads#alternate_method_using_downloadurl) is to send the authorization token separately using the Authorization
header. Modify the Javascript above to send the download URL and token separately, then use something like the code below instead. If you want to use file_get_contents
, see PHP file_get_contents() and headers关于如何发送自定义headers。注意你需要有Bearer
字在令牌之前!
<?php
$filename = 'temp.jpg';
$ch = curl_init($_POST['fileurl']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$_POST['authtoken']));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
echo 'Curl error: ' . curl_error($ch);
curl_close($ch);
file_put_contents($filename, $data);
?>
方法二:Server-side(使用PHP)
使用此方法,在PHP完成第1、3、4步,Javascript只完成第2步。
quickstart.php
此页面检查 session 中是否有访问令牌,如果没有,它将重定向用户以进行身份验证。如果有,它会显示选择器和表单。在选择器 Javascript 代码中,注意使用的 oAuthToken 是通过 PHP 从服务器获取的!资料来源:Use Google Picker without logging in with Google account (with OAuth)。然后表单向此页面提交 POST 请求并下载文件。
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
// Ref: https://developers.google.com/drive/v2/reference/files/get
function downloadFile($service, $file) {
$downloadUrl = $file->getDownloadUrl();
if ($downloadUrl) {
$request = new Google_Http_Request($downloadUrl, 'GET', null, null);
$httpRequest = $service->getClient()->getAuth()->authenticatedRequest($request);
if ($httpRequest->getResponseHttpCode() == 200) {
return $httpRequest->getResponseBody();
} else {
// An error occurred.
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
if (isset($_POST['fileid'])){
$drive_service = new Google_Service_Drive($client);
$file = $drive_service->files->get($_POST['fileid']);
$data = downloadFile($drive_service, $file);
file_put_contents('temp.jpg', $data);
echo "file uploaded";
exit();
}
} else {
$redirect_uri = 'http://localhost/drivepicker-php/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
exit();
}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = '';
// Replace with your own App ID. (Its the first number in your Client ID)
var appId = ""
var pickerApiLoaded = false;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
// Create and render a Picker object
function createPicker() {
if (pickerApiLoaded) {
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
//view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
//.enableFeature(google.picker.Feature.NAV_HIDDEN)
//.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken('<?= json_decode($client->getAccessToken())->access_token; ?>')
.addView(view)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
document.getElementById("fileid").value = fileId;
}
}
</script>
</head>
<body>
<form action="quickstart.php" method="post">
<label for="fileid">File ID</label><input type="text" name="fileid" id="fileid">
<input type="submit">
</form>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
</html>
oauth2callback.php
OAuth 回调的帮助文件。
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://localhost/drivepicker-php/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_READONLY);
if (!isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://localhost/drivepicker-php/quickstart.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>