Download google drive file with v3 api - php

The Google drive api seems confusing when it comes to downloading files. I've been able to list all of the files and even downloaded few files but got stuck while downloading Google docs.
Why don't really they have common method for downloading a file but rather two different methods: Get and Export. When I don't need any conversion for the file, Why do I need to specify the Mime type for Export? Also, while listing files, the Mime type for all the files is always null. e.g
#foreach ($files->getFiles() as $file)
{{ $file->getMimeType() }} // empty string / null
#endforeach
Reference to getMimeType
Here's what I've done so far
public function listFiles(Request $request)
client = $this->getClient();
$service = new Google_Service_Drive($client);
$optParams = array(
'q' => 'fullText contains \'"abc"\'',
'pageSize' => 10,
'fields' => 'nextPageToken, files(id, name)'
);
$files = $service->files->listFiles($optParams);
}
public function downloadFile($file_id)
{
$client = $this->getClient();
$service = new Google_Service_Drive($client);
$file = null;
$file = $service->files->export($file_id, 'application/pdf', array(
'alt' => 'media'
)); // I really need to get rid of Mimetype(application/pdf), It should download the exact same file
}
Update
I have managed to solve the mime type problem by providing the field in the list.
$optParams = array(
'q' => 'fullText contains \'"basheer"\'',
'pageSize' => 10,
'fields' => 'nextPageToken, files(id, name, mimeType)' //<--
);
But now when I try to download load the file, it throws the following error
The requested conversion is not supported. "domain": "global", "reason": "badRequest",
// request('mimeType') = application/vnd.google-apps.spreadsheet
$file = $service->files->export($file_id, request('mimeType'), array(
'alt' => 'media'
));
Your answers and comments will be appreciated.
Thanks

Related

Drive API uploaded file always has zero size with PHP client

I'm trying to upload files into a google drive in a specific folder using a service account. It all appears to work - but the files always show up with 0 size. I've found a couple of very similar questions on here but none of the answers have worked.
The code I'm using is:
putenv('GOOGLE_APPLICATION_CREDENTIALS = ' . $home_path . '../google-oauth-credentials.json');
try {
$gclient = new Google\Client();
$gclient->useApplicationDefaultCredentials();
$gclient->addScope('https://www.googleapis.com/auth/drive');
$driveService = new Google\Service\Drive($gclient);
$content = file_get_contents('testfile.txt');
$fileMetadata = new Google\Service\Drive\DriveFile(array(
'name' => 'test.txt',
'parents' => array('{PARENT_ID}'),
'description' => 'Test Description'
));
$file = $driveService->files->create($fileMetadata, array([
'data' => $content,
'mimeType' => 'text/plain',
'uploadType' => 'multipart',
'fields' => 'id'
]));
printf("File ID: %s\n", $file->id);
echo '<br>';
echo '<pre>' . print_r($file,1) . '</pre>';
echo '<h1>Content:</h1>';
echo ($content);
} catch(Exception $e) {
echo "Error Message: ".$e;
};
With {PARENT_ID} being the ID of the folder the files should be saved in.
This is meant to be uploading pdf files but I've switched to a simple text file to rule out a mime issue. With the PDF's I was using "application/pdf" as the mimeType, I've also tried "application/octet-stream" for both pdf and text and I've tried putting the mimeType in the $fileMetaData as well as in the request body as it currently is.
I've tried using 'uploadType' of 'media' as well as some other answers had suggested.
I've also tried with and without the 'fields' => 'id' whose purpose I can't seem to find in the API docs - but which was shown in various examples and other answers. I get the same results with or without it.
No luck. With any of that I get files with correct meta data....but they never have any content and are just 0 bytes in size.
I added the lines echoing out $content to confirm that file_get_contents is loading the correct file and its content to rule out a problem with what I'm passing to the request.
I'm loading the google api client through composer with
composer require google/apiclient:^2.12.1
And it seems to be working correctly as I can create google sheets, and edit their contents as well as create files...just the files always wind up having 0 size.
Try dropping the 'uploadType' => 'multipart',
// Upload a file to the users Google Drive account
try{
$filePath = "image.png";
$fileMetadata = new Drive\DriveFile();
$fileMetadata->setName('testfile.txt');
$fileMetadata->setMimeType('text/plain');
$content = file_get_contents($filePath);
$mimeType=mime_content_type($filePath);
$request = $service->files->create($fileMetadata, array(
'data' => $content,
'mimeType' => $mimeType,
'fields' => 'id'));
printf("File ID: %s\n", $request->id);
}
catch(Exception $e) {
// TODO(developer) - handle error appropriately
echo 'Message: ' .$e->getMessage();
}
I found the problem.
The error was in:
$file = $driveService->files->create($fileMetadata, array([
'data' => $content,
'mimeType' => 'text/plain',
'uploadType' => 'multipart',
'fields' => 'id'
]));
Which came more or less verbatim from:
https://developers.google.com/drive/api/guides/manage-uploads
I'm also not sure why the 'fields' parameter is included since v3 create doesn't appear to support that.
Note the "array([])" It's defining an array inside the array.
Removing the [] or the array() solves the problem by correctly passing the intended array instead of passing an array containing the intended array.

Google Drive API: Why doesn't uploaded file appear in my Google Drive until I view the webContentLink

I am new to the Google Drive API and have gotten to the point where I have successfully uploaded a file and subsequently am able to list out the file(s) that I uploaded. Something that confused me was that files I uploaded did NOT appear in my Google Drive until I viewed the file via the webContentLink address. Only after viewing the file in a browser via the webContentLink address did the file then magically appear in my Google Drive.
I have seen similar questions on stackoverflow but those seem to be related to the fact that a parent ID was not specified in the upload. I am just curious as to why the file doesn't appear in my Google Drive unless I view the file separately via the webContentLink link. Here is my upload code:
function insertFile($service, $title, $description, $parentId, $mimeType, $filename)
{
$file = new Google_Service_Drive_DriveFile();
$file->setName($title);
$file->setDescription($description);
$file->setMimeType($mimeType);
// Set the parent folder.
if ($parentId != null) {
$parent = new ParentReference();
$parent->setId($parentId);
$file->setParents(array($parent));
}
try {
$data = file_get_contents($filename);
$createdFile = $service->files->create($file, array('data' => $data, 'mimeType' => $mimeType));
$Permission = new \Google_Service_Drive_Permission(array(
'type' => 'anyone',
'role' => "reader",
'additionalRoles' => []
));
$service->permissions->create(
$createdFile->getId(), $Permission, array('fields' => 'id'));
return $createdFile;
} catch (Exception $e) {
die("An error occurred: " . $e->getMessage());
}
}
$title="Berkobien Tree";
$description="BerkobienTree upload";
$parentId=null;
$mimeType='application/pdf';
$filename='D:\WWWRoot\babycity.com\httpdocs\BerkobienTree.pdf';
$createdFile = insertFile($service, $title, $description, $parentId, $mimeType, $filename);
it's most likely due to some latence coming from your connection.
When I upload new files, or move files between drives with the API it most often appears instantly, but some other times it takes a few seconds (not more than one minute though). But if you refresh your drive's page emptying cache it should do the trick.
When I create a folder I simply give these informations :
$folderFile = new \Google_Service_Drive_DriveFile([
'name' => $folderName,
'mimeType' => 'application/vnd.google-apps.folder',
'parents' => [$receivingFolderId],
'id' => $service->files->generateIds(['count' => 1, 'space' => 'drive']),
]);
$service->files->create($folderFile, [
'includePermissionsForView' => 'published',
'supportsAllDrives' => true,
]);
and for creating a file / copying a file
// Create new file with seedFile's name and mimeType
$newFile = new \Google_Service_Drive_DriveFile([
'name' => $name,
'mimeType' => $mimeType,
'parents' => [$PARENT_ID],
]);
// Copy the original file data into the newly created file
$service->files->copy($originalFileId, $newFile, [
'supportsAllDrives' => true,
]);
/*
So because I'm using a Team drive and an external drive for this process
I do not have the rights to delete a file from an external drive so I simply remove its parent, and the file is now an 'orphan'.
It is not a suppression of the file !
In my case it fits my needs.
*/
// Remove the original file's parent folder to delete it from his folder
$service->files->update($originalFileId, (new \Google_Service_Drive_DriveFile()), [
'includePermissionsForView' => 'published',
'removeParents' => $originalFileId->getParents(),
'supportsAllDrives' => true,
]);
As you mentioned, you already can create a file, and from your code I can see that it works. So I think your problem just comes from a latence in your internet connection ? Maybe try to set the parent a different way ? I'm just speculating at this point.

Google Drive Api PHP multipart upload empty content

my issue is the following.
When using the google drive api V3 and php to upload a file to google drive, the file uploaded is empty, with a filesize of 0 bytes. All the metadata uploads no problem.
session_start();
$file_tmp=$_SESSION['file_tmp'];
$drive = new Google_Service_Drive($client);
$data = file_get_contents($file_tmp);
$file = new Google_Service_Drive_DriveFile(array(
'data' => $data,
'mimeType' => $file_type,
'name' => $file_name,
'description'=>$lolol,
'uploadType' => 'multipart',
'parents' => array($folderID),
'uploadType' => 'multipart'
));
$createdFile = $drive->files->create($file);
For anyone wondering, if I echo $file_tmp I get a path such as /private/var/tmp/phpDpmi83 .(I got this from a html form with input type file)
Originally i didn't have an UploadType and other forums said that was the issue, but I added that and still nothing.
Any suggestions?
I believe your goal as follows.
You want to upload a file with multipart/form-data to the specific folder in Google Drive using Drive API.
You want to achieve this using googleapis for PHP.
In your script, $drive can be used for uploading the file.
For this, how about this answer?
Modification point:
In your script, please separate the metadata and file content. By this, I think that your script works.
When above point is reflected to your script, it becomes as follows.
Modified script:
session_start();
$file_tmp=$_SESSION['file_tmp'];
$drive = new Google_Service_Drive($client);
$data = file_get_contents($file_tmp);
// I modified below script.
$file = new Google_Service_Drive_DriveFile(array(
'mimeType' => $file_type,
'name' => $file_name,
'description'=>$lolol,
'parents' => array($folderID),
));
$file_content = array(
'data' => $data,
'uploadType' => 'multipart'
);
$createdFile = $drive->files->create($file, $file_content);
Note:
In this modification, it supposes that $data is the file content. If your $file_tmp cannot be used, please test using a sample file.
In this case, the maximum file size is 5 MB. Please be careful this.
References:
Upload file data
googleapis for PHP

How can I create a folder within a Team Drive with the Google API?

I'm struggling to create a folder within a Team Drive using the Google API PHP Client Library.
I am using a service account and impersonating a user (myself) who is a member of the Team Drive and can list the contents of the drive. However, when I create a folder it always creates it in 'My Drive' rather than the Team Drive specified.
Attempt 1
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope("https://www.googleapis.com/auth/drive");
$client->setSubject('user#mydomain.com');
$service = new Google_Service_Drive($client);
$folderId = '0AIuzzEYPQu9CUk9PVA';
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'New Test Folder',
'mimeType' => 'application/vnd.google-apps.folder',
'supportsAllDrives' => true,
'parents' => ['0AIuzzEYPQu9CUk9PVA']
));
Attempt 2
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'New Test Folder',
'mimeType' => 'application/vnd.google-apps.folder',
'supportsAllDrives' => true,
'driveId' => '0AIuzzEYPQu9CUk9PVA'
));
UPDATE Attempt 3
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'Hello 123',
'supportsAllDrives' => true,
'mimeType' => 'application/vnd.google-apps.folder',
'parents' => ['0AIuzzEYPQu9CUk9PVA']
));
$file = $service->files->create($fileMetadata, array(
'fields' => 'id'));
printf("Folder ID: %s\n", $file->id);
Attempt 3 gives this error:
Fatal error: Uncaught Google_Service_Exception: { "error": { "errors": [ { "domain": "global", "reason": "notFound", "message": "File not found: 0AIuzzEYPQu9CUk9PVA.", "locationType": "parameter", "location": "fileId" } ]
I have read all the (limited) documentation regarding Team Drive and the API and understand that a folder/file within a Team Drive can only have one parent (The Team Drive's ID) so I have tried variations of the parent as an array and string.
The folder is created correctly, just in the wrong place.
The documentation is not very clear on how to handle the creation of folders inside Teamdrives but this are the two things you need to take note of:
1.'supportsAllDrives' => true, is part of the optional parameters and not part of the file metadata.
2. Both the parent and the driveId should be included as part of the metadata
So here is an example on how to achieve this:
$service = new Google_Service_Drive($client);
$parent = "0AA3C8xRqwerLglUk9PVA"; //Teamdrive ID
//Create new folder
$file = new Google_Service_Drive_DriveFile(array(
'name' => 'Test Folder',
'mimeType' => 'application/vnd.google-apps.folder',
'driveId' => $parent,
'parents' => array($parent)
));
$optParams = array(
'fields' => 'id',
'supportsAllDrives' => true,
);
$createdFile = $service->files->create($file, $optParams);
print "Created Folder: ".$createdFile->id;
Please Note: You will need the client library version 2.1.3 or greater.

Adding Metada and Options to S3 Objects when uploading a directory

I am successfully uploading folders to S3 using ->uploadDirectory(). Several hundred folders have 100's, or 1,000's of images contained within them with so using PutObject() for each file hardly seemed to make sense. The upload works, and all goes well, but the ACL, StorageClass, and metadata is not being included in the upload.
According to the docs at http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html#uploading-a-directory-to-a-bucket , the following code should accomplished this. It is further documented with the putObject() function that is also cited.
I can find no examples of this function using anything but a directory and bucket, so fail to see what might be wrong with it. Any ideas why the data in $options is being ignored?
$aws = Aws::factory('config.php');
$s3 = $aws->get('S3');
$dir = 'c:\myfolder\myfiles';
$bucket = 'mybucket;
$keyPrefix = "ABC/myfiles/";
$options = array(
'ACL' => 'public-read',
'StorageClass' => 'REDUCED_REDUNDANCY',
'Metadata'=> array(
'MyVal1'=>'Something',
'MyVal2'=>'Something else'
)
);
$result = $s3->uploadDirectory($dir, $bucket, $keyPrefix, $options);
Parameters to provide to putObject or createMultipartUpload should be in the params option, not provided as top-level values in the options array. Try declaring your options as follows:
$options = array(
'params' => array(
'ACL' => 'public-read',
'StorageClass' => 'REDUCED_REDUNDANCY',
'Metadata'=> array(
'MyVal1'=>'Something',
'MyVal2'=>'Something else',
),
),
);

Categories