Задание PHP Cron для резервного копирования на Google Диск

#php #cron #google-drive-api

#php #cron #google-drive-api

Вопрос:

Я пытаюсь настроить задание cron, которое будет создавать резервные копии различных файлов с моего сервера на Google Диск. Я просмотрел множество решений, и, похоже, ни одно из них не работает! Самое близкое, что у меня есть (с использованием OAuth), это:

 <?php
/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

require_once __DIR__ . '/../vendor/autoload.php';
require_once "base.php";

echo pageHeader("File Upload - Uploading a large file");

/*************************************************
 * Ensure you've downloaded your oauth credentials
 ************************************************/
if (!$oauth_credentials = getOAuthCredentialsFile()) {
  echo missingOAuth2CredentialsWarning();
  return;
}

/************************************************
 * The redirect URI is to the current page, e.g:
 * http://localhost:8080/large-file-upload.php
 ************************************************/
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
echo "<br>$redirect_uri";
$client = new Google_Client();
echo "<br>got client";
$client->setAuthConfig($oauth_credentials);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/drive");
$service = new Google_Service_Drive($client);

// add "?logout" to the URL to remove a token from the session
if (isset($_REQUEST['logout'])) {
  unset($_SESSION['upload_token']);
}
echo "<br>got service";
/************************************************
 * If we have a code back from the OAuth 2.0 flow,
 * we need to exchange that with the
 * Google_Client::fetchAccessTokenWithAuthCode()
 * function. We store the resultant access token
 * bundle in the session, and redirect to ourself.
 ************************************************/
if (isset($_GET['code'])) {
echo "<br>getting token";
  $token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
echo "<br>Got token";
  $client->setAccessToken($token);

  // store in the session also
  $_SESSION['upload_token'] = $token;

  // redirect back to the example
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

// set the access token as part of the client
if (!empty($_SESSION['upload_token'])) {
echo "<br>getting access token";
  $client->setAccessToken($_SESSION['upload_token']);
  if ($client->isAccessTokenExpired()) {
    unset($_SESSION['upload_token']);
  }
} else {
  $authUrl = $client->createAuthUrl();
}
echo "<br>Ready to go";

/************************************************
 * If we're signed in then lets try to upload our
 * file.
 ************************************************/
if ($_SERVER['REQUEST_METHOD'] == 'POST' amp;amp; $client->getAccessToken()) {
  /************************************************
   * We'll setup an empty 20MB file to upload.
   ************************************************/
  DEFINE("TESTFILE", 'testfile.txt');
  if (!file_exists(TESTFILE)) {
    $fh = fopen(TESTFILE, 'w');
    fseek($fh, 1024*1024*20);
    fwrite($fh, "!", 1);
    fclose($fh);
  }

  $file = new Google_Service_Drive_DriveFile();
  $file->name = "Big File";
  $chunkSizeBytes = 1 * 1024 * 1024;
echo "<br>created file";

  // Call the API with the media upload, defer so it doesn't immediately return.
  $client->setDefer(true);
  $request = $service->files->create($file);

  // Create a media file upload to represent our upload process.
  $media = new Google_Http_MediaFileUpload(
      $client,
      $request,
      'text/plain',
      null,
      true,
      $chunkSizeBytes
  );
  $media->setFileSize(filesize(TESTFILE));
echo "<br>created media";

  // Upload the various chunks. $status will be false until the process is
  // complete.
  $status = false;
  $handle = fopen(TESTFILE, "rb");
  while (!$status amp;amp; !feof($handle)) {
    // read until you get $chunkSizeBytes from TESTFILE
    // fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
    // An example of a read buffered file is when reading from a URL
    $chunk = readVideoChunk($handle, $chunkSizeBytes);
    $status = $media->nextChunk($chunk);
  }

  // The final value of $status will be the data from the API for the object
  // that has been uploaded.
  $result = false;
  if ($status != false) {
    $result = $status;
  }

  fclose($handle);
}

function readVideoChunk ($handle, $chunkSize)
{
    $byteCount = 0;
    $giantChunk = "";
    while (!feof($handle)) {
        // fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
        $chunk = fread($handle, 8192);
        $byteCount  = strlen($chunk);
        $giantChunk .= $chunk;
        if ($byteCount >= $chunkSize)
        {
            return $giantChunk;
        }
    }
    return $giantChunk;
}
?>

<div class="box">
<?php if (isset($authUrl)): ?>
  <div class="request">
    <a class='login' href='<?= $authUrl ?>'>Connect Me!</a>
  </div>
<?php elseif($_SERVER['REQUEST_METHOD'] == 'POST'): ?>
  <div class="shortened">
    <p>Your call was successful! Check your drive for this file:</p>
    <p><a href="https://drive.google.com/open?id=<?= $result->id ?>" target="_blank"><?= $result->name ?></a></p>
    <p>Now try <a href="/large-file-download.php">downloading a large file from Drive</a>.
  </div>
<?php else: ?>
  <form method="POST">
    <input type="submit" value="Click here to upload a large (20MB) test file" />
  </form>
<?php endif ?>
</div>

<?= pageFooter(__FILE__) ?>
  

Но, похоже, оно дошло до комментария «Получение токена» и останавливается — покопался в коде Google API с дополнительной трассировкой, но, конечно, мне не нужно этого делать?
Да, у меня есть учетные данные oauth, настроенные для этого — проходит мимо них

Комментарии:

1. Я не вижу никаких материалов cron в том, что вы опубликовали.

2. Верно — хотя ничто в файле php не говорит вам, должен ли он выполняться в cron или нет. Гораздо проще сначала протестировать файлы вне среды cron, поэтому на самом деле это файл, который я пытаюсь запустить непосредственно из своего браузера

3. Я получил этот пример от github.com/googleapis/google-api-php-client/blob/master /…

Ответ №1:

Вам следует рассмотреть возможность использования учетной записи службы, если вы работаете с заданием cron, которое необходимо будет запускать без вмешательства пользователя.

Просто обратите внимание, что учетная запись службы является фиктивной. Файлы, загруженные учетной записью службы, будут принадлежать учетной записи службы. Вам нужно настроить учетную запись службы, чтобы предоставить вашей личной учетной записи права доступа к файлам, которые она загружает.

Также файлы будут загружены в учетную запись Service accounts drive, если вы не дадите ей разрешения на запись в каталог вашей учетной записи personal Drive и загрузку в него вместо этого.

 // Load the Google API PHP Client Library.
require_once __DIR__ . '/vendor/autoload.php';

// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');

/**
 * Gets the Google client refreshing auth if needed.
 * Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
 * Initializes a client object.
 * @return A google client object.
 */
function getGoogleClient() {
    return getServiceAccountClient();
}

/**
 * Builds the Google client object.
 * Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
 * Scopes will need to be changed depending upon the API's being accessed. 
 * array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
 * List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
 * @return A google client object.
 */
function getServiceAccountClient() {
    try {   
        // Create and configure a new client object.        
        $client = new Google_Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope([YOUR SCOPES HERE]);
        return $client;
    } catch (Exception $e) {
        print "An error occurred: " . $e->getMessage();
    }
}
  

Комментарии:

1. Спасибо — это продвигает меня дальше, чем другой код, поэтому я продолжу этот путь!