新手谷歌驱动API(PHP)混乱 - 使用什么指南/库?

Kev*_*Sol 1 php api google-drive-api

我有一个移动网站m.example.com - 我希望访问者从手机中选择Google云端硬盘中的文件,并将其发送到托管m.example.com的服务器.基本上仿真<input type="file">桌面上的简单文件上传.

据我所知,工作流程如下:

1)用户选择带有Picker的文件,该文件将所选文件的元数据发送到我的网站客户端(即手机/平板电脑上运行的HTML/Javascript)

2)我通过ajax或只是一个表单隐藏字段将它发送到我的服务器

3)我的服务器向Google API请求获取文件,然后将其存储在服务器的文件系统中

所以我需要帮助:

a)上述步骤是否正确,还有其他方法可以做到这一点,甚至是我可以使用的服务,这将允许我的网站用户从几个云存储提供商之一中选择他们的文件?

a)假设我的步骤是正确的,这是唯一的方法,我被困在3)部分 - 服务器与API谈话.

到目前为止,我已经停止了这里的选择器 - Google picker auth popup被阻止并获得了文件URL.我还没有完成2)但是,我现在只是手动将文件URL放入我的下载脚本中.

我正在使用PHP,我想要下载到我的服务器的文件可以是公共的或私有的,这取决于最终用户.

我迷失在API文档中(如在手册页中,而不是谷歌文档),并且与https://developers.google.com/api-client-library/php/start/get_started(调用此API文档)相混淆和https://developers.google.com/drive/web/quickstart/quickstart-php(调用此Drive文档) - 这两个不同的API?

我按照API文档中的链接从这里安装了客户端:https://github.com/google/google-api-php-client,但在Drive docs上尝试"第3步:设置示例"时得到很多错误,例如找不到的文件,类不是fount等等,所以这让我觉得这里有两个不同的API /客户端 - 有人可以指点我正确的方向开始吗?

UPDATE

我已经从这个https://developers.google.com/api-client-library/php/start/get_started链接的github安装了PHP客户端

这看起来像:

在此输入图像描述

我在examples目录中运行了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 /谷歌/ Client.php所以我编辑放在require_once使用的.

现在得到Failed opening required 'src/contrib/Google_DriveService.php' - 再次搜索该文件yeilds没有结果,但有一个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';
Run Code Online (Sandbox Code Playgroud)

现在:

require_once 'src/Google/Client.php';
require_once 'src/Google/Service/Drive.php';
Run Code Online (Sandbox Code Playgroud)

现在开始了 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日.

小智 7

你是对的,驱动器快速入门指南已经过时,它指的是Google Code上的旧版Google PHP客户端API库,而不是GitHub上的新版本.因此,快速入门指南不适用于您下载的PHP客户端库.此外,快速入门指南代码旨在以PHP命令行模式而不是在服务器上执行.

为了回答这个问题,我提出了一些子答案:

  1. 如何使用PHP客户端库
  2. 如何使用Google Picker选择文件并将文件放到服务器上

将Google PHP客户端库与Google Drive API一起使用

请尝试使用此页面:https://developers.google.com/api-client-library/php/auth/web-app,其中有一个示例,说明如何使用新的 PHP库在用户的Google云端硬盘上列出文件,包括整个OAuth程序.

不幸的是,即使这有点过时(包含路径已过时,现已弃用).因此(以及StackOverflow的完整性)这里有一些代码.我在我的Web服务器根目录中使用了子目录drivetest; 根据需要更改URL.

请注意,您需要在Google的开发者控制台中获取"Web应用程序"的客户端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));
    }   

?>
Run Code Online (Sandbox Code Playgroud)

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));
    }

?>
Run Code Online (Sandbox Code Playgroud)

使用Google文件选择器选择文件

对于您的使用案例,您可能最好使用Google Picker https://developers.google.com/picker/docs/,它为您实现整个浏览和选择文件,并且只为您提供ID文件.所需步骤摘要:

  1. 获取访问令牌(身份验证)
  2. 使用选择器让用户选择文件
  3. 使用从选择器返回的文件ID来获取下载URL
  4. 从下载URL下载文件

我们可以通过两种方式(客户端或服务器端)执行此操作:

方法1:客户端

使用此方法,步骤1 - 3在Javascript中完成,并且仅在PHP中完成步骤4.使用这种方法,我们甚至不需要PHP客户端库!

这是一个例子(改编自上面链接中的示例代码和http://webdevrefinery.com/forums/topic/12931-dropbox-google-drive-file-pickers/):

picker.html

此文件在页面加载时启动filepicker并将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>
Run Code Online (Sandbox Code Playgroud)

然后,我们将表单提交到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);

?>
Run Code Online (Sandbox Code Playgroud)

更官方的方式(遵循https://developers.google.com/drive/web/manage-downloads#alternate_method_using_downloadurl)是使用Authorization标题单独发送授权令牌.修改上面的Javascript以分别发送下载URL和令牌,然后使用类似下面的代码.如果要使用file_get_contents,请参阅PHP file_get_contents()和有关如何发送自定义标头的标头.请注意,您需要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);

?>
Run Code Online (Sandbox Code Playgroud)

方法2:服务器端(使用PHP)

使用此方法,步骤1,3和4在PHP中完成,并且仅在Javascript中完成步骤2.

quickstart.php

此页面检查会话中是否存在访问令牌,如果没有,则重定向用户进行身份验证.如果有,它会显示选择器和表单.在选择器Javascript代码中,请注意所使用的oAuthToken是从服务器使用PHP获得的!来源:使用Google Picker而无需使用Google帐户登录(使用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>
Run Code Online (Sandbox Code Playgroud)

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));
    }

?>
Run Code Online (Sandbox Code Playgroud)