Alan Wells
Alan Wells

Reputation: 31310

Google - App Engine - API PHP - Warning: mkdir(): The local filesystem is readonly, mkdir failed - Allow local filesystem to make directory

The google-api-php-client library has a file named File.php, and that file is in the src/Google/Cache directory. That file returns an error from line 149:

if (! mkdir($storageDir, 0755, true)) {

The error is:

Warning: mkdir(): The local filesystem is readonly, mkdir failed in C:\Users\NoName\Documents\academic-being-90217\google-api-php-client\src\Google\Cache\File.php on line 149

I'm testing code by running it from Google App Engine Launcher on my local computer.

Obviously, my local filesystem won't allow PHP to make a directory. How can I allow PHP to make the directory? I'm using windows 7.

In the PHP documentation, it states:

Note: mode is ignored on Windows.

In the Client.php file, the Google_Client class has a method isAppEngine(). As a test, I ran that method (locally from my computer) and it returned nothing. So, . . . on my computer, testing an App Engine project, the google-api-php-client doesn't detect that this is for App Engine. If it were running on App Engine, when the $config object is created, it checks if the code is running on App Engine, and

// Automatically use Memcache if we're in AppEngine.

if ($this->isAppEngine()) {
  // Automatically use Memcache if we're in AppEngine.
  $config->setCacheClass('Google_Cache_Memcache');
}

So, I'm wondering if the reason that the code is trying to create a new directory on my computer, is to use it for Cache, because it didn't detect that the code is running on App Engine. (which it isn't)

I guess I could deploy a development project to App Engine, and test the OAuth2 functionality with echo statements. I'd need to constantly be deploying every time I wanted to test. If the OAuth is working, obviously I won't need to change anything. But how will I test new versions locally on my machine, if I can't authorize OAuth2?

I deployed the following code to App Engine, and ran the code from the server. It did not display an error to the browser. Then I refreshed the window, and got a msg from inside an IF check, that the service token had been set. So, it looks like it's authorizing my app as a service. So, I'm assuming that because I ran the code from App Engine, it used Mem Cache instead of creating a Cache directory, and saving data to a file.

<?php
session_start();

//The php file loaded below outputs information to the user in the browser
include_once "templates/base.php";
//The autoload.php file loads the entire API library I think.  It avoids needing to call specific files.
require_once realpath(dirname(__FILE__) . '/google-api-php-client/src/Google/autoload.php');

//The following three lines are the credentials
$client_id = 'my ID here.apps.googleusercontent.com'; //Client ID
$service_account_name = 'My name [email protected]'; //Email Address
$key_file_location = 'Test Project-file-name.p12'; //key.p12

//Display a page header to the user in their browser
echo pageHeader("Service Account Access");

//Check if the credentials are present and assigned to their variable names
if (!strlen($client_id)
    || !strlen($service_account_name)
    || !strlen($key_file_location)) {
  echo missingServiceAccountDetailsWarning();
}

//The Google_Client Class is in file Client.php
//Create a Google_Client object and use it to acquire an access token
$client = new Google_Client();
/*
foreach($client as $key => $value) {
  echo $key." - ".'<br>';
}
*/

//The object $client was just created in the above line of code.  Call the function 'setApplicationName' that is inside of
//the $client object.
$client->setApplicationName("Client_Drive_Examples");

$service = new Google_Service_Drive($client);

/************************************************
  If we have an access token, we can carry on.
  Otherwise, we'll get one with the help of an
  assertion credential. In other examples the list
  of scopes was managed by the Client, but here
  we have to list them manually. We also supply
  the service account
 ************************************************/
if (isset($_SESSION['service_token'])) {
  echo 'There is a service token';

  $client->setAccessToken($_SESSION['service_token']);
}

$key = file_get_contents($key_file_location);

//echo 'the $key: ' . $key;
//echo '$service_account_name: ' . $service_account_name;

/*
https://www.googleapis.com/auth/drive - View and manage the files in your Google Drive
https://www.googleapis.com/auth/drive.file - View and manage files that you have created with this app
https://spreadsheets.google.com/feeds/ - Manage your spreadsheets
*/
$scopes = array('https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file');

$cred = new Google_Auth_AssertionCredentials(
    $service_account_name,
    $scopes,
    $key
);

$client->setAssertionCredentials($cred);

if ($client->getAuth()->isAccessTokenExpired()) {
  $client->getAuth()->refreshTokenWithAssertion($cred);
}


$_SESSION['service_token'] = $client->getAccessToken();

echo 'end of code';
?>

Upvotes: 0

Views: 1164

Answers (2)

DanPride
DanPride

Reputation: 150

It sort of does tho. You just add your directory paths to the filename and it has a new long filename, but it accomplishes the same thing, keeping you backward compatible with the older max files per folder type of filesystem assuming you branch your code for environment

Upvotes: 1

Dave W. Smith
Dave W. Smith

Reputation: 24966

App Engine does not support creating directories dynamically.

Upvotes: 3

Related Questions