phpdownloadgoogle-drive-apigoogle-api-php-clientgoogle-drive-shared-drive

Google Drive API download files from shared drive


I am trying to download a file from a shared drive via the Google API. I always get the response that the file was not found (code 404).

This does not work even if I have full access (admin) to the folder. The files are created by me. If I have saved them in "My folder", this works without any problems.

I use the export endpoint for Google's own files, to export as PDF: https://developers.google.com/drive/api/reference/rest/v3/files/export

And for all other files I use the get endpoint: https://developers.google.com/drive/api/reference/rest/v3/files/get

I'm working with the Google API PHP Client (v2.15.3): https://github.com/googleapis/google-api-php-client/

The Google Drive API is activated in the Google Console. The OAuth 2.0 client ID for web applications is also set up. With all rights that are available with the Google Drive API.

How can I retrieve the files from shared drive?

Here is the code where I am trying to retrieve the file:

<?php

    require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';

    $client = new Google_Client();

    # Todo: need to change
    $client->setAuthConfig( __DIR__ . DIRECTORY_SEPARATOR . 'client_secret.json' );
    $client->addScope( Google_Service_Drive::DRIVE );
    $client->setAccessType( 'offline' );

    $protocol   = ( ! empty( $_SERVER[ 'HTTPS' ] ) && $_SERVER[ 'HTTPS' ] !== 'off' || $_SERVER[ 'SERVER_PORT' ] == 443 ) ? "https://" : "http://";
    $currentUrl = $protocol . $_SERVER[ 'HTTP_HOST' ] . $_SERVER[ 'PHP_SELF' ];

    $client->setRedirectUri( $currentUrl );

    if ( ! isset( $_GET[ 'code' ] ) ) {
        $auth_url = $client->createAuthUrl();
        header( 'Location: ' . filter_var( $auth_url, FILTER_SANITIZE_URL ) );
        exit;
    }
    else {
        var_dump( $_GET[ 'code' ] );
        var_dump( $client->fetchAccessTokenWithAuthCode( $_GET[ 'code' ] ) );

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

        $driveService   = new Google_Service_Drive( $client );
        
        # Todo: need to change
        $google_file_id = 'YOUR_FILE_ID_HERE';

        try {
            $file_metadata = $driveService->files->get( $google_file_id );
            $response      = $driveService->files->get( $google_file_id, array( 'alt' => 'media' ) );
            $content       = $response->getBody()->getContents();

            if ( $file_metadata->getMimeType() && str_starts_with( $file_metadata->getMimeType(), 'application/vnd.google-apps.' ) ) {
                $response  = $driveService->files->export( $google_file_id, 'application/pdf', [ 'alt' => 'media' ] );
                $file_name = $file_metadata->getName() . '.pdf';
            }
            else {
                $response  = $driveService->files->get( $google_file_id, [ 'alt' => 'media', 'supportsAllDrives' => true ] );
                $file_name = $file_metadata->getName();
            }

            file_put_contents( __DIR__ . DIRECTORY_SEPARATOR . $file_name, $content );

            echo "Stored!";

        }
        catch ( Exception $e ) {
            echo '<pre>';
            var_export( $e );
            echo '</pre>';
        }
    }

Solution

  • In your script, I think that supportsAllDrives is required to be used for retrieving the file metadata and the file content by files->get. So, how about the following modification?

    Modified script:

    $client->setAccessToken( $access_token );
    
    $driveService  = new Google_Service_Drive( $client );
    $file_metadata = $driveService->files->get( $google_file_id, ['fields' => "name,mimeType", "supportsAllDrives" => true] ); // or ['fields' => "*", "supportsAllDrives" => true]
    
    if ( $file_metadata->getMimeType() && str_starts_with( $file_metadata->getMimeType(), 'application/vnd.google-apps.' ) ) {
        $response  = $driveService->files->export( $google_file_id, 'application/pdf');
        $file_path = $routine_path . $file_metadata->getName() . '.pdf';
    }
    else {
        $response  = $driveService->files->get( $google_file_id, [ 'alt' => 'media', "supportsAllDrives" => true ] );
        $file_path = $routine_path . $file_metadata->getName();
    }
    
    $content = $response->getBody()->getContents();
    
    if ( file_put_contents( $file_path, $content ) ) {
        $file_paths[] = $file_path;
    }
    

    Reference: