使用Google Drive API + Parse将文件存储在一个云端硬盘帐户中

时间:2015-08-26 15:39:31

标签: javascript parse-platform google-drive-api google-api-js-client

我正在尝试使用单个Google云端硬盘帐户作为网络服务器。'我有一个Android应用程序,需要能够存储和检索图片。我的想法是使用Parse来帮助管理所有内容并将我的存储容量扩展到Parse的免费金额之外。

基本上,我将拥有一个Google云端硬盘帐户和一个Parse项目。当用户想要存储文件时,他/她将文件上传到Parse,Parse使用单个Google Drive帐户进行身份验证(使用CloudCode),Parse将文件上传到Drive,将URL存储到表中的文件中,然后删除来自Parse云存储的文件。我打算给存储这些文件的文件夹提供私有写访问和公共读访问权限,这样客户就不必向Parse请求发送

这样做的目的是为我的应用程序获得更多存储空间。 (亚马逊S3只提供5g,Parse提供1g,DropBox 2g,谷歌云存储我不认为他们有免费计划,而驱动器提供15g,但我也听说过谷歌照片集成谷歌驱动器可能会给我无限存储图片)

由于谷歌硬盘并没有真正做到这一点,我有一些难以弄清楚如何将所有部分组合在一起。

我已经查看了question这似乎不适用于我的情况,因为我将能够在安全服务器上运行所有写操作。 (我还读过我需要存储一个刷新令牌,使用这种方法也应该是安全的)

我看过this,但很多链接已经过时了,所以对我没什么帮助。

我查看了this,但这似乎是在授权应用使用用户的个人文件。

我还读过,如果是Web应用程序帐户,我可能需要使用服务帐户,但同样,我一直在阅读的信息还不是很清楚。在我看来,这是因为Drive不是以这种方式工作的。

要点:

1

有人能指出我使用Parse Cloud Code(服务器端Javascript)将文件写入单个Google云端硬盘帐户的正确方向吗?

2:

如果上述问题可以解决/可能,那么Google发布的Google Photo是否意味着我的图片存储空间基本无限?

1 个答案:

答案 0 :(得分:2)

行。因此,经过数小时的研究和测试,我想出了一种让它发挥作用的方法。

Google的API身份验证过程至少可以说有点令人困惑。一般程序如下:

  1. 要求用户授予范围INSERT YOUR PROJECT HERE
  2. YOUR SCOPE的访问权限
  3. 用户可以接受或拒绝该请求
  4. 如果用户接受,您可以检索访问令牌(更重要的是刷新令牌)
  5. 获得刷新令牌后,您可以随时获取新的访问令牌以进行API调用。
  6. 因此,这样做的全部目标是进行需要刷新代码的API调用(特别是驱动)。

    主要的困难是,( AS FAR AS I WOW )无法验证用户并获取Parse CloudCode内的访问代码。 但是 ,我有一个理论认为,如果我能以某种方式验证CloudCode之外的用户帐户,您仍然可以GET / POST来自CloudCode函数的请求。 (更具体地说:Parse.Cloud.httpRequest

    有许多方法/平台允许您对用户进行身份验证以获取刷新代码。最容易访问的方法可能是使用Android / Java版本的API,因为任何拥有计算机的人都可以运行Android模拟器,但我可以轻松访问支持PHP的网站,因此我选择使用PHP。但同样,这部分过程可以在许多不同的平台上完成。

    第一步是安装Google API Client Library for PHPGithub)。有几种不同的方法可以在您的服务器上安装它,但由于我只需要它来获取刷新令牌,我选择在运行时动态包含它(也因为我没有快速访问我的php.ini文件)。

    (在我继续之前请注意:我不是PHP开发人员,所以如果我做任何奇怪或多余的事情,请告诉我;我只是在展示我为使其工作而做了什么)

    要做到这一点,我只需下载一个库的副本,将其上传到我的服务器,并在我使用该库的所有文件中包含以下行:

    set_include_path(get_include_path() . PATH_SEPARATOR . 'google-api-php-client-master/src');
    

    其中google-api-php-client-master/src是src文件夹的路径。

    完成后,您必须对用户进行身份验证。以下两个文件将用户发送到身份验证页面,然后在屏幕上打印该用户的刷新代码。

    index.php

    <?php
        set_include_path(get_include_path() . PATH_SEPARATOR . 'google-api-php-client-master/src');
        require_once 'google-api-php-client-master/src/Google/autoload.php'; // or wherever autoload.php is located 
    
        session_start();
    
        $client = new Google_Client();
        $client->setAuthConfigFile('client_secrets.json'); //You can download this file from your developer console under OAuth 2.0 client IDs
        $client->addScope(Google_Service_Drive::DRIVE); //Scope that grants full access to user's Google Drive
        $client->setAccessType("offline"); //Important so a refresh code is returned
    
        if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
            print($_SESSION['refresh_token']);
        } else {
            $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
            header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
        }
    ?>
    

    oauth2callback.php

    <?php
    
        set_include_path(get_include_path() . PATH_SEPARATOR . 'google-api-php-client-master/src');
    
        require_once 'google-api-php-client-master/src/Google/autoload.php';
    
        session_start();
    
        $client = new Google_Client();
        $client->setAuthConfigFile('client_secrets.json');
        $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
        $client->addScope(Google_Service_Drive::DRIVE);
        $client->setAccessType("offline");
    
        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();
          $_SESSION['refresh_token'] = $client->getRefreshToken(); //Important to clear the session variable after you have the token saved somewhere
          $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; //Redirects to index.php
          header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
        }
    
    ?>
    

    关于此代码的几个重要说明:

    1. 您需要确保已创建appropriate credentials(Web应用程序)
    2. 您需要将正确的重定向URI添加到OAuth 2.0客户端ID。它应该是http://yourdomain.com/oauth2callback.php
    3. 您需要将client_secrets.json文件上传到您的服务器。您可以转到开发人员控制台并单击OAuth 2.0客户端ID列表最右侧的下载图标来获取此信息。
    4. 出于安全原因,在复制刷新令牌后,您应该清除会话变量。
    5. 总而言之,我们创建了一个简单的程序,可以打印出特定用户的刷新令牌。您需要将该代码复制下来并保存以供日后使用。

      即使你有刷新令牌,你也需要一种获取访问令牌来进行API调用的方法。 (如果没有访问令牌,您就无法进行API调用,并且因为它们每隔3600秒就会过期,所以在需要时需要一种新方法)

      以下是完成此步骤的Parse CloudCode:

      Parse.Cloud.define("getAccessToken", function(request, response) {
          Parse.Cloud.httpRequest({
              method: "POST",
              url: 'https://www.googleapis.com/oauth2/v3/token/',
              params: {
                  refresh_token : 'INSERT_REFRESH_TOKEN_HERE',
                  client_id : 'INSERT_CLIENT_ID_HERE',
                  client_secret : 'INSERT_CLIENT_SECRET_HERE',
                  grant_type : 'refresh_token'
              }
          }).then(function(httpResponse) {
            response.success(httpResponse.text);
          }, function(httpResponse) {
            response.error('Request failed with response code ' + httpResponse.status);
          });
      });
      

      此函数发送访问令牌请求。您可以使用该令牌做任何您想做的事情;它存储在httpResponse.text中(如果请求成功)。请注意,grant_type应该是refresh_token而不是您的刷新令牌。

      获得访问令牌后,您可以在刷新令牌的范围内自由地进行API调用。例如:

      Parse.Cloud.define("sendRequest", function(request, response) {
          Parse.Cloud.httpRequest({
              method: "GET",
              url: 'https://www.googleapis.com/drive/v2/about',
              params: {
                  access_token : 'INSERT_YOUR_ACCESS_TOKEN_HERE'
              }
          }).then(function(httpResponse) {
            response.success(httpResponse.text);
          }, function(httpResponse) {
            response.error('Request failed with response code ' + httpResponse.status);
          });
      });
      

      此函数返回有关与该刷新令牌关联的驱动器帐户的信息。

      关于我的第二个问题,我还没有做足够的研究来了解答案,但我打算在此找到并发布。