Search code examples
reactjssymfonygoogle-drive-apigoogle-oauthgoogle-drive-picker

Download Google Drive file with PHP Symfony


I have already tinkered in several docs and forums and I know that the subject has already been discussed but none of the solutions proposed have helped me resolve my problem. Maybe it's the config that's missing, that's why I'm counting on your help because I don't know what to do.

technical stack: PHP : 8.2 Symfony : 6.4 ReactJs : 18.3

My need is not complicated, the user clicks on a button to display all the images that exist in his drive and in shared drives I m using react-google-drive-picker and I have access to desired images

If I use file.id in postman to retrieve the file and upload it to my server I always get Error 404 File not found and I don't know why

What I tested and not working (always 404 not found):

  • File created by me in my drive
  • File created by me in shared drive
  • File not created by me in shared drive
  • All scopes in $client->addScope ; all together and separately
  • The account using this files normally have permissions to download files (specially the file created my me in my drive)

Any help please ?

Display Google Grive Images : Works fine

import useDrivePicker from 'react-google-drive-picker';

export const Drive = () => {

const CLIENT_ID = "MY_CLIENT_ID";
const API_KEY = "API_KEY; // generated with Google Picker API in Google console not with Google Drive API

const [openPicker] = useDrivePicker();

const handleOpenPicker = () => {
        openPicker({
            clientId: CLIENT_ID,
            developerKey: API_KEY,
            viewId: "DOCS_IMAGES",
            showUploadFolders: true,
            supportDrives: true,
            locale: 'fr',
            // customScopes: ['https://www.googleapis.com/auth/drive'],
            callbackFunction: (data) => {
                if (data.action === 'cancel') {
                    console.log('User clicked cancel/close button')
                }
                if (data.docs) {
                    const file = data.docs[0];
                    console.log(file); // I can see my file object here
                }
            },
        })
    }

    return (
        <>
            <button onClick={() => handleOpenPicker()}>Open Picker</button>
        </>
    )
}

Retrieve file from Google Drive with same credentials : Not working

<?php

use Google\Client;
use Google\Service\Drive;
use Google\Service\Exception;

// .... 
$request = json_decode($this->requestStack->getCurrentRequest()->getContent(), true);
        $credentials = "../config/client_secret.json"; // I get this file when I created ID clients OAuth in Google console  
        $client = new Client();
        $client->setAuthConfig($credentials);
        $client->setDeveloperKey("SAME_API_KEY_FRONT_END");
        $client->setClientId("SAME_CLIENT_ID_FRONT_END");
        $client->addScope([Drive::DRIVE, Drive::DRIVE_FILE, Drive::DRIVE_METADATA, Drive::DRIVE_READONLY]);
        $driveService = new Drive($client);
        $response = $driveService->files->get($request["file"], [
                'alt' => 'media',
                'supportsAllDrives' => true
            ]
        );
        dd($response);

Solution

  • My Bad, like I said, maybe I m missing some configuration.

    Solution was to create un account service in google console and share files with his email address

    Code That works

    $request = json_decode($this->requestStack->getCurrentRequest()->getContent(), true);
    // after created the account service, you will be able to download file like project-id-hash.json
        $credentials = "PATH/TO/AUTH/FILE/GENERATED/IN/GOOGLE/CONSOLE";  
        $client = new Client();
        $client->setAuthConfig($credentials);
        $client->setDeveloperKey("API_KEY");
        $client->setClientId("CLIENT_ID");
        $client->addScope(Drive::DRIVE);
        $driveService = new Drive($client);
        $response = $driveService->files->get($request["file"], [
                'alt' => 'media',
                'supportsAllDrives' => true
            ]
        );
        if ($response->getStatusCode() === Response::HTTP_OK) {
            $b64 = base64_encode($response->getBody()->getContents());
            $filePath = $this->drive . $request["name"];
    
    
            file_put_contents($filePath, base64_decode($b64));
        }