I am very new to the google cloud storage.
I want to create folder in bucket using php coding. I have searched a quite few sites and on 1 i saw it was written:
"Creating a folder inside a bucket will create a placeholder object named after the directory, has no data content and the mimetype application/x-directory. Directory placeholder objects created in Google Storage Manager are not supported."
I could not understand what it is trying to say. How can i create folder please help me out. I tried using the following code:
$req = new Google_HttpRequest("http://commondatastorage.googleapis.com/bucket/myfoldertrial");
$req->setRequestHeaders(array(
'x-goog-project-id' => 21212,
'x-goog-acl' => 'public-read',
'Content-Type' => 'application/x-directory'
));
$req->setRequestMethod('PUT');
$req->setPostBody('myfoldertrial');
I am using the API from following link:
Google API for PHP
Please help me out creating folder using PHP.
You probably don't actually need to create a folder.
Google Storage isn't a tree structure like your operating system's filesystem uses, all Objects are stored in buckets at the top level. However you can give an Object a name with slashes in it, so it will kind of look like it is in a folder - Users/username/docs/2012/09/21/activity.csv is a perfectly good name for an Object and doesn't need any supporting folders.
Once you've got Objects with this sort of scheme in place, you can list them as if you were viewing the contents of a folder with the delimiter and prefix parameters as per these docs.
So if you only wanted to create myfoldertrial so you could upload example.png into it, there's no need to create the folder, you can just upload straight to myfoldertrial/example.png.
Sometimes, in a CMS, you need to create a directory first before able to upload file into it, so the mouse click can trigger an event to take the path as the base folder, then do a batch upload.
It's a file browser, they say.
This code below might help.
<?php
$privateKeyFile = '{{full/path/to/*.p12}}';
$newDirectory = '{{path/of/new/directory/}}'; // remember to end it with a slash.
/**
* Authentication
*/
$client = new Google_Client();
$client->setApplicationName('Create a new folder');
$client->setClientId($clientId);
$scopes = array('https://www.googleapis.com/auth/devstorage.full_control');
$client->setScopes($scopes);
$service = new Google_Service_Storage($client);
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
if (!file_exists($privateKeyFile)) {
die('missing the location of primary key file, given: ' . $privateKeyFile);
}
$key = file_get_contents($privateKeyFile);
$cred = new Google_Auth_AssertionCredentials(
$clientEmailAddress
, $scopes
, $key
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
/**
* Creating Folder
*/
try {
/* create empty file that acts as folder */
$postBody = new Google_Service_Storage_StorageObject();
$postBody->setName($newDirectory);
$postBody->setSize(0);
$created = $service->objects->insert($bucketName, $postBody, array(
'name' => $newDirectory,
'uploadType' => 'media',
'projection' => 'full',
'data' => '',
));
} catch (Exception $ex) {
echo $ex->getMessage() . "\n<pre>";
print_r($ex->getTraceAsString());
echo '</pre>';
die();
}
echo 'EOF';
You can simply create folder by providing it in a filepath when you are uploading it,
i.e. your url should be https://storage.googleapis.com///?GoogleAccessId=id#developer.gserviceaccount.com&Expires=1410875751&Signature=SIGNATURE
Related
i want to upload a file to google cloud storage using google client php library on github. Am able to upload file to cloud storage but am not able to upload to a directory in cloud storage. i get the error message No such object: bucketName/abc/test.jpg
$client = new Google_Client();
putenv('GOOGLE_APPLICATION_CREDENTIALS=files/google_cloud.json');
$client->useApplicationDefaultCredentials();
$storage = new Google\Cloud\Storage\StorageClient([
'projectId' => $googleprojectID
]);
$sPath = "files/com/test.jpg";
$objectName = "/abc/test.jpg";
$bucketName = $googlebucketName;
$bucket = $storage->bucket($bucketName);
$bucket->upload( fopen($sPath, 'r') );
$object = $bucket->object($objectName);
$info = $object->update(['acl' => []], ['predefinedAcl' => 'PUBLICREAD']);
First of all, let me share with you this documentation page where you will find the complete reference for the Google Cloud Storage PHP Client Library. More specifically, if you have a look at the upload() method, you will see that in order to set the name of the object uploaded (and therefore its location, given that GCS has a flat namespace), you have to use the options parameter, which can contain a name field pointing to the right location to upload.
Also, note that the correct object name should not start with a slash /, given that it will automatically be added after the bucket name. Therefore, you should modify your code to add something like this:
$sPath = "files/com/test.jpg";
$objectName = "abc/test.jpg"; # Note the removal of "/" here
$options = [
'name' => $objectName
];
$bucketName = $googlebucketName;
$bucket = $storage->bucket($bucketName);
$bucket -> upload(
fopen($sPath, 'r'),
$options
);
I am trying to create folder using google drive api. I am able to get file id at the end. but i am not able to my folder in google drive. it seems some permission issue?
$scopes = array(
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.appdata','https://www.googleapis.com/auth/drive.apps.readonly',
'https://www.googleapis.com/auth/drive.metadata','https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.readonly','https://www.googleapis.com/auth/drive.photos.readonly'
);
$creds = new Google_Auth_AssertionCredentials(
$serviceAccountName,
$scopes,
file_get_contents($keyFile)
);
$client = new Google_Client();
$client->setApplicationName($appName);
$client->setClientId($clientId);
$client->setAssertionCredentials($creds);
$service = new Google_Service_Drive($client);
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'Invoices',
'permissions' => array('type'=>'anyone','role'=>'reader','allowFileDiscovery'=>1),
'mimeType' => 'application/vnd.google-apps.folder'));
$file = $service->files->create($fileMetadata, array());
printf("File ID: %s\n", $file->id);
The files that are being created belong to the API account email (something like api-service-account#yourproject.iam.gserviceaccount.com. If you go to the drive URL:
https://docs.google.com/document/d/{ID}, you will get a "Permission Denied, request access" page.
The service account email is not related to your user email.
In order to create files with your user, you need to create an OAauth token authorization.
Create the OAuth credentials following the steps "Step 1: Turn on the Drive API" on this page
Modify your script, by following the example on this page, you can have:
use Google_Client;
use Google_Service_Drive;
use Google_Service_Drive_DriveFile;
...
$file = 'root/to/your/credentials.json';
$client = new Google_Client();
$client->setScopes([
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.apps.readonly',
'https://www.googleapis.com/auth/drive.metadata',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/drive.photos.readonly'
]);
$client->setAuthConfig($file);
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
// You will need to open this url
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
$accessToken = $client->authenticate($authCode);
file_put_contents($credentialsPath, $accessToken);
printf("Credentials saved to %s\n", $credentialsPath);
$client->setAccessToken(json_decode($accessToken, true));
$service = new Google_Service_Drive($client);
$metadata = new Google_Service_Drive_DriveFile([
'name' => 'testing drive',
'mimeType' => "application/vnd.google-apps.document"
]);
$file = $service->files->create($metadata, []);
print_r($file);
The file should be in your Drive home directory.
By the way, I suggest you try the new version google/apiclient:2.0.2 (which is still on Beta, but works okay).
Mayrop answer is partially right.
The files that are being created belong to the API account email (something like api-service-account#yourproject.iam.gserviceaccount.com.
You need to give permission to owner of that account like
$newPermission = new Google_Service_Drive_Permission();
$value="email id";
$type="user";
$role="writer";
$newPermission->setValue($value);
$newPermission->setType($type);
$newPermission->setRole($role);
try {
$res= $service->permissions->insert($fileId, $newPermission);
print_r($res);
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
You will see that folder in Shared with me. You can also add in your drive manually.
You can also disable sending notification via email using
$service->permissions->insert($fileId, $newPermission,array('sendNotificationEmails'=>false));
Hope this will work for you.
Yes, It seems permissions issue. Try removing
'permissions' => array('type'=>'anyone','role'=>'reader','allowFileDiscovery'=>1),
from
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'Invoices',
'permissions' => array('type'=>'anyone','role'=>'reader','allowFileDiscovery'=>1),
'mimeType' => 'application/vnd.google-apps.folder'));
so I have worked over it, and finally got the full working solution for Google Drive V3 in Php. As follows:
You can go through this gist for full code and better understanding:
https://gist.github.com/KartikWatts/22dc9eb20980b5b4e041ddcaf04caf9e
First of all adding to the answer from #Hitu Bansal:
This code works fine:
$this->newPermission = new Google_Service_Drive_Permission();
$value=<YOUR EMAIL ADDRESS>;
$type="user";
$role="reader";
$this->newPermission->setEmailAddress($value);
$this->newPermission->setType($type);
$this->newPermission->setRole($role);
$this->newPermission->allowFileDiscovery;
try {
$res= $this->service->permissions->create($folder_id, $this->newPermission);
print_r($res);
catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
If, instead you want to share the link with anyone: You may use
$type="anyone";
$this->newPermission->setType($type);
$this->newPermission->setRole($role);
$this->newPermission->allowFileDiscovery;
$this->newPermission->view;
NOTE:
In this case, setEmailAddress() shall be removed.
IMPORTANT: In case of 'anyone', the folder will not be visible in your personal drive for sure, but you can still visit and interact with the folder as per given roles by visiting the link making use of the folder_id that you know already. So, you can visit the link as: https://drive.google.com/drive/u/5/folders/**{folder_id}** It will be publically accessible now.
For more clear reference to the parameters along with a description, this is really helpful: https://developers.google.com/drive/api/v3/reference/permissions#methods
NOTE: In my personal opinion, a better way to work with Google Drive API is to create the folder first manually (if workflow allows it), then upload the files using the folder_id of that created folder. Remember, In case folder is created manually, permission shall be provided to the Service Account email-id before.
While permission issue is the main cause of this problem. What I did to make the folders or files appear after I uploaded it with service account was to specify the parent folder. If you upload / create folder / files without parent folder ID, that object's owner will be the service account that you are using.
By specifying parent ID, it will use the inherited permissions.
Here's the code I use in php (google/apiclient)
$driveFile = new Google\Service\Drive\DriveFile();
$driveFile->name = 'New Folder';
$driveFile->mimeType = 'application/vnd.google-apps.folder';
$driveFile->parents = ['123456789qwertyuiop'];
$result = $service->files->create($driveFile);
Using the code below
define('DRIVE_SCOPE', 'https://www.googleapis.com/auth/drive');
define('SERVICE_ACCOUNT_EMAIL', 'xxx.iam.gserviceaccount.com');
define('SERVICE_ACCOUNT_PKCS12_FILE_PATH', 'xxx');
function buildService($userEmail) {
$key = file_get_contents(SERVICE_ACCOUNT_PKCS12_FILE_PATH);
$auth = new Google_Auth_AssertionCredentials(
SERVICE_ACCOUNT_EMAIL,
array(DRIVE_SCOPE),
$key);
//$auth->sub = $userEmail;
$client = new Google_Client();
$client->setAssertionCredentials($auth);
return new Google_Service_Drive($client);
}
$service = buildService('xxx.apps.googleusercontent.com');
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'Invoices',
'mimeType' => 'application/vnd.google-apps.folder'
));
$file = $service->files->create($fileMetadata, array(
'fields' => 'id'
));
printf("Folder ID: %s\n", $file->id);
I have been trying to create a folder on my drive account through PHP. I believe everything is configured correctly and I am getting a result
Folder ID: 0B2nllBpB_k0NQWFNUjlSc0NUdE0
But the folder is not being created on my drive account. The same goes with creating files as well. It keeps returning an ID but nothing is actually created. What exactly am I doing wrong?
Your current code is authenticating as the service account and creating a file. The resultant file would then only be accessible to the service account, not your Google user. You can confirm this by doing a list of files instead of a create in your code, you'll get back the files you've previously created.
Your code has sub= commented out. Uncommented that line and make sure you've followed the domain-wide delegation instructions so that your code can authenticate and act as your Google user.
I have been struggling for quite a while now; via Google drives PHP API, I am able to create a sub folder or add files to an existing folder, But trying to place another sub folder or a file within a sub folder, seems impossible.
After research, I came across the Children function, but don't understand how to apply it, even after checking the Google documentation on this page: [https://developers.google.com/drive/v2/reference/children/insert][1]
The code I am using to add an image to a folder is:
//Insert a file into client specific folder
$file = new Google_Service_Drive_DriveFile();
$file->setTitle(uniqid().'.jpg');
$file->setDescription('A test document');
$file->setMimeType('image/jpeg');
$data = file_get_contents('a.jpg');
$parent = new Google_Service_Drive_ParentReference(); //previously Google_ParentReference
$parent->setId($folderid); //$folderid = determined folder id
$file->setParents(array($parent));
$createdFile = $service->files->insert($file, array(
'data' => $data,
'mimeType' => 'image/jpeg',
'uploadType' => 'multipart'
));
How would I proceed to upload this image to a specific subfolder, of which the ID is already determined?
Update:
This is my combined code trying to:
Create new_sub_folder1 with a parent of existing_folder, and store the returned ID
Create new_file1 with a parent of new_sub_folder1, using the ID stored in step 1
$service = new Google_Service_Drive($client);
//create sub folder
$folder = new Google_Service_Drive_DriveFile();
//Setup the folder to create
$folder->setTitle('new_sub_folder1');
$folder->setMimeType('application/vnd.google-apps.folder');
//Create the Folder within existing_folder
$parentid = '0B40CySVsd_Jaa1BzVUQwLUFyODA';
//Set the Parent Folder to existing_folder
$parent = new Google_Service_Drive_ParentReference(); //previously Google_ParentReference
$parent->setId($parentid);
$folder->setParents(array($parent));
//now create the client specific folder new_sub_folder
try {
$createdFile = $service->files->insert($folder, array(
'mimeType' => 'application/vnd.google-apps.folder',
));
// Return the created folder's id
$subfolderid = $createdFile->id;
echo $subfolderid;
return $createdFile->id;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
//Insert a file into client specific folder new_sub_folder
$file = new Google_Service_Drive_DriveFile();
$file->setTitle(uniqid().'.jpg');
$file->setDescription('A test document');
$file->setMimeType('image/jpeg');
$data = file_get_contents('a.jpg');
//Set the Parent Folder to new_sub_folder
$parent = new Google_Service_Drive_ParentReference(); //previously Google_ParentReference
$parent->setId($subfolderid);
$file->setParents(array($parent));
$createdFile = $service->files->insert($file, array(
'data' => $data,
'mimeType' => 'image/jpeg',
'uploadType' => 'multipart'
));
print_r($createdFile);
But only new_sub_folder1 is created, and no file is added to this folder.
Update:
The image is not added anywhere with this code. If I apply the same method to add .jpg to the existing_folder, by its ID, there are no issues. As soon as I use the sub_folder_1's ID, nothing is created - same method, different ID.
Think of the folders as a train. Where your file (in this case a folder) has to be attached to 2 other train carts in order to work. The previous one is the parent and the next one is the child. If you specify a parent, but not a child for a folder then the train is incomplete. Sometimes it doesn't matter that the train is not complete, but if you want to use at least 2 levels of files then you must use parent and children references.
Your base folder may have root as its parent, then this folder could be the father of another sub-folder but it needs to be specified that it has children if you plan to use several level hierarchy for it to have a complete reference. So check this code:
$foldID=$id;
$folder4=new Google_Service_Drive_DriveFile();
$folder4->setTitle($folderName);
$folder4->setMimeType('application/vnd.google-apps.folder');
$parent4=new Google_Service_Drive_ParentReference();
$parent4->setId($foldID);
$folder4->setParents(array($parent4));
try {
$createdFile4 = $service->files->insert($folder4, array(
'mimeType' => 'application/vnd.google-apps.folder',
));
}
catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
$foldId4=$createdFile4->id;
$newChild4=new Google_Service_Drive_ChildReference();
$newChild4->setId($createdFile4->id);
try{
$service->children->insert($foldID,$newChild4);
}
catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
A few things about the code:
foldID is my kind of master or root folder. I create a new DriveFile, assign the folder specifications, assign a parent reference of my master folder, try to insert it, then specify a child reference with the children->insert(ID OF MY MASTER FOLDER, ID OF THE CREATED FOLDER). The reference now is complete, and the subfolder should be treated as such. For another sub-sub-folder, just rinse and repeat with the right parameters. I have a directory structure of approximately 6 or 7 level of folders and files, so it is possible so it's just to index the files correctly.
My guess is that you've misunderstood how folders work in Drive. In Drive it's important to think of folders as being more like labels.
You say "I am not able to: existing_folder -> new_sub_folder1->new_file1, new_file2,"
In Drive, this is simply:-
Create new_sub_folder1 with a parent of existing_folder, and store the returned ID
Create new_file1 with a parent of new_sub_folder1, using the ID stored in step 1
struggling to understand the oauth2 token and refresh token processes
ive got this code
$url = 'https://www.googleapis.com/oauth2/v3/token';
$data = array('client_id' => 'clientid', 'client_secret' => 'secret','refresh_token' => 'token','grant_type' => 'refresh_token');
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded",
'method' => 'POST',
'approval_prompt'=>'force',
'access_type'=>'offline',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
that code above gives me an access token , and i followed this link suggested by one fellow stackoverflower, pinoyyid, BUT , im confunsed on how to correctly use the resulting access token to access drive and copy a file...
all the process ive seen usually involves $client = new Google_Client() and im not sure on how to use the whole POST http://..... thing, so basically i need to figure out if i use the access token i got with the code above in a new instance of google client, or i simply do a post to a url with necesary info ( which im not clear on also ) any help/clarification is appreciated guys really
EDIT #1
what i want to achieve is to allow the end user to access my drive via my webpage, to let them copy a spreadsheet in my drive , and access it via my website, to store data on the spreadsheet,the spreadsheet will always be on my drive, never on the end user
EDIT #2
code as per your posts is as follows, using the service account,,,,the files are inside that gmail account which i created on the api console a service account
<?php
require 'Google/autoload.php';
$client = new Google_Client();
// Replace this with your application name.
$client->setApplicationName("TEST");
// Replace this with the service you are using.
$service = new Google_Service_Drive($client);
// This file location should point to the private key file.
$key = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/number-privatekey.p12');
$user_to_impersonate = 'admin#testpr.com';
$cred = new Google_Auth_AssertionCredentials(
'number#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/drive'), ****//this here has to be drive not drive.file
$key,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
$user_to_impersonate
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$originFileId = "longnumber";
$copyTitle = 'copied';
$newfile = copyFile($service, $originFileId, $copyTitle);
print_r($newfile);
function copyFile($service, $originFileId, $copyTitle)
{
$copiedFile = new Google_Service_Drive_DriveFile();
$copiedFile->setTitle($copyTitle);
try {
return $service->files->copy($originFileId, $copiedFile);
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
return NULL;
}
?>
so got it working just now, ty all for your time guys really and edited my post to reflect the dang thing
If you want to give the end user access to your drive, you have to give your application authority to make API calls on behalf of a user (in this case you) in your domain. For this you have to set up a service account and generate a p12 key in the Google Developers Console. You have to enter the https://www.googleapis.com/auth/drive API scope in your Admin Console as well.
Full explanation and examples can be found here: https://developers.google.com/api-client-library/php/auth/service-accounts.
To achieve this you also need the Google API's client library: https://github.com/google/google-api-php-client (also mentioned in the Google manual).
Code example to let users make API calls on behalf of one of your accounts: https://developers.google.com/api-client-library/php/guide/aaa_oauth2_service