PHPackages                             realmatrix/flysystem-google-drive-ext - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. realmatrix/flysystem-google-drive-ext

ActiveLibrary[File &amp; Storage](/categories/file-storage)

realmatrix/flysystem-google-drive-ext
=====================================

Flysystem adapter for Google Drive with seamless virtual&lt;=&gt;display path translation

2.x-dev(1y ago)05Apache-2.0PHP ^7.2 | ^8.0

Since Oct 4Pushed 1y agoCompare

[ Source](https://github.com/realmatrix/flysystem-google-drive-ext)[ Packagist](https://packagist.org/packages/realmatrix/flysystem-google-drive-ext)[ Fund](https://ko-fi.com/masbug)[ RSS](/packages/realmatrix-flysystem-google-drive-ext/feed)WikiDiscussions 2.x Synced 1mo ago

READMEChangelogDependencies (6)Versions (1)Used By (0)

Flysystem adapter for Google Drive with seamless virtual&lt;=&gt;display path translation
=========================================================================================

[](#flysystem-adapter-for-google-drive-with-seamless-virtualdisplay-path-translation)

[![Flysystem API version](https://camo.githubusercontent.com/677d74bd1a8a4e9399fe29ab771bf6d89ecadae7e4fca113e6d0ec1c35f9f16c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466c7973797374656d2532304150492d56322d626c75653f7374796c653d666c61742d737175617265)](https://github.com/thephpleague/flysystem/)[![Latest Version on Packagist](https://camo.githubusercontent.com/380a0f1c886f662592103810974d46ed9562e100fbd4ac974dfb23900888d9dc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d61736275672f666c7973797374656d2d676f6f676c652d64726976652d6578742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/masbug/flysystem-google-drive-ext)[![License](https://camo.githubusercontent.com/753b222389d983713c05b305cd5ba4a064fcbe8dc060e90da88b74ee0401340a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d417061636865253230322e302d626c75652e7376673f7374796c653d666c61742d737175617265)](https://opensource.org/licenses/Apache-2.0)[![Build Status](https://camo.githubusercontent.com/56d98e9e8020864c007138c5952b0d9d7001e638a5165c4347691d0e88bde342/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f636f6d2f6d61736275672f666c7973797374656d2d676f6f676c652d64726976652d6578742f322e782e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.com/masbug/flysystem-google-drive-ext)[![StyleCI](https://camo.githubusercontent.com/a51cbfc6b461cf4ca5fa9281e52869dce9d74b1bae7715ffc6625807695abf8f/68747470733a2f2f7374796c6563692e696f2f7265706f732f3131333433343532322f736869656c643f6272616e63683d322e78)](https://styleci.io/repos/113434522)[![Total Downloads](https://camo.githubusercontent.com/d6d5d71f685e7e5f3097453058f740075a0f7e6cb14bde3ca0b0c5a18cc989c7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d61736275672f666c7973797374656d2d676f6f676c652d64726976652d6578742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/masbug/flysystem-google-drive-ext)

Google uses unique IDs for each folder and file. This makes it difficult to integrate with other storage services which use normal paths.

This [Flysystem adapter](https://github.com/thephpleague/flysystem) works around that problem by seamlessly translating paths from "display paths" to "virtual paths", and vice versa.

For example: virtual path `/Xa3X9GlR6EmbnY1RLVTk5VUtOVkk/0B3X9GlR6EmbnY1RLVTk5VUtOVkk` becomes `/My Nice Dir/myFile.ext` and all ID handling is hidden.

Installation
------------

[](#installation)

- For **Flysystem V2/V3** or **Laravel &gt;= 9.x.x**

```
composer require masbug/flysystem-google-drive-ext
```

- For **Flysystem V1** or **Laravel &lt;= 8.x.x** use 1.x.x version of the package

```
composer require masbug/flysystem-google-drive-ext:"^1.0.0"
```

Getting Google Keys
-------------------

[](#getting-google-keys)

#### Please follow [Google Docs](https://developers.google.com/drive/v3/web/enable-sdk) to obtain your `client ID, client secret & refresh token`.

[](#please-follow-google-docs-to-obtain-your-client-id-client-secret--refresh-token)

#### In addition you can also check these easy-to-follow tutorial by [@ivanvermeyen](https://github.com/ivanvermeyen/laravel-google-drive-demo)

[](#in-addition-you-can-also-check-these-easy-to-follow-tutorial-by-ivanvermeyen)

- [Getting your Client ID and Secret](https://github.com/ivanvermeyen/laravel-google-drive-demo/blob/master/README/1-getting-your-dlient-id-and-secret.md)
- [Getting your Refresh Token](https://github.com/ivanvermeyen/laravel-google-drive-demo/blob/master/README/2-getting-your-refresh-token.md)

Usage
-----

[](#usage)

```
$client = new \Google\Client();
$client->setClientId([client_id]);
$client->setClientSecret([client_secret]);
$client->refreshToken([refresh_token]);
$client->setApplicationName('My Google Drive App');

$service = new \Google\Service\Drive($client);

// variant 1
$adapter = new \Masbug\Flysystem\GoogleDriveAdapter($service, 'My_App_Root');

// variant 2: with extra options and query parameters
$adapter2 = new \Masbug\Flysystem\GoogleDriveAdapter(
    $service,
    'My_App_Root',
    [
        'useDisplayPaths' => true, /* this is the default */

        /* These are global parameters sent to server along with per API parameters. Please see https://cloud.google.com/apis/docs/system-parameters for more info. */
        'parameters' => [
            /* This example tells the remote server to perform quota checks per unique user id. Otherwise the quota would be per client IP. */
            'quotaUser' => (string)$some_unique_per_user_id
        ]
    ]
);

// variant 3: connect to team drive
$adapter3 = new \Masbug\Flysystem\GoogleDriveAdapter(
    $service,
    'My_App_Root',
    [
        'teamDriveId' => '0GF9IioKDqJsRGk9PVA'
    ]
);

// variant 4: connect to a folder shared with you
$adapter4 = new \Masbug\Flysystem\GoogleDriveAdapter(
    $service,
    'My_App_Root',
    [
        'sharedFolderId' => '0GF9IioKDqJsRGk9PVA'
    ]
);

$fs = new \League\Flysystem\Filesystem($adapter, new \League\Flysystem\Config([\League\Flysystem\Config::OPTION_VISIBILITY => \League\Flysystem\Visibility::PRIVATE]));
```

```
// List selected root folder contents
$contents = $fs->listContents('', true /* is_recursive */);

// List specific folder contents
$contents = $fs->listContents('MyFolder', true /* is_recursive */);
```

##### File upload

[](#file-upload)

```
// Upload a file
$local_filepath = '/home/user/downloads/file_to_upload.ext';
$remote_filepath = 'MyFolder/file.ext';

$localAdapter = new \League\Flysystem\Local\LocalFilesystemAdapter('/');
$localfs = new \League\Flysystem\Filesystem($localAdapter, [\League\Flysystem\Config::OPTION_VISIBILITY => \League\Flysystem\Visibility::PRIVATE]);

try {
    $time = Carbon::now();
    $fs->writeStream($remote_filepath, $localfs->readStream($local_filepath), new \League\Flysystem\Config());

    $speed = !(float)$time->diffInSeconds() ? 0 :filesize($local_filepath) / (float)$time->diffInSeconds();
    echo 'Elapsed time: '.$time->diffForHumans(null, true).PHP_EOL;
    echo 'Speed: '. number_format($speed/1024,2) . ' KB/s'.PHP_EOL;
} catch(\League\Flysystem\UnableToWriteFile $e) {
    echo 'UnableToWriteFile!'.PHP_EOL.$e->getMessage();
}

// NOTE: Remote folders are automatically created.
```

##### File download

[](#file-download)

```
// Download a file
$remote_filepath = 'MyFolder/file.ext';
$local_filepath = '/home/user/downloads/file.ext';

$localAdapter = new \League\Flysystem\Local\LocalFilesystemAdapter('/');
$localfs = new \League\Flysystem\Filesystem($localAdapter, [\League\Flysystem\Config::OPTION_VISIBILITY => \League\Flysystem\Visibility::PRIVATE]);

try {
    $time = Carbon::now();
    $localfs->writeStream($local_filepath, $fs->readStream($remote_filepath), new \League\Flysystem\Config());

    $speed = !(float)$time->diffInSeconds() ? 0 :filesize($local_filepath) / (float)$time->diffInSeconds();
    echo 'Elapsed time: '.$time->diffForHumans(null, true).PHP_EOL;
    echo 'Speed: '. number_format($speed/1024,2) . ' KB/s'.PHP_EOL;
} catch(\League\Flysystem\UnableToWriteFile $e) {
    echo 'UnableToWriteFile!'.PHP_EOL.$e->getMessage();
}
```

##### How to get TeamDrive list and IDs

[](#how-to-get-teamdrive-list-and-ids)

```
$drives = $fs->getAdapter()->getService()->teamdrives->listTeamdrives()->getTeamDrives();
foreach ($drives as $drive) {
    echo 'TeamDrive: ' . $drive->name . PHP_EOL;
    echo 'ID: ' . $drive->id . PHP_EOL. PHP_EOL;
}
```

##### How permanently deletes all of the user's trashed files

[](#how-permanently-deletes-all-of-the-users-trashed-files)

```
$fs->getAdapter()->emptyTrash([]);
```

Using with Laravel Framework
----------------------------

[](#using-with-laravel-framework)

##### Update `.env` file with google keys

[](#update-env-file-with-google-keys)

Add the keys you created to your `.env` file and set `google` as your default cloud storage. You can copy the `.env.example` file and fill in the blanks.

```
FILESYSTEM_CLOUD=google
GOOGLE_DRIVE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_DRIVE_CLIENT_SECRET=xxx
GOOGLE_DRIVE_REFRESH_TOKEN=xxx
GOOGLE_DRIVE_FOLDER=
#GOOGLE_DRIVE_TEAM_DRIVE_ID=xxx
#GOOGLE_DRIVE_SHARED_FOLDER_ID=xxx

# you can use more accounts, only add more configs
#SECOND_GOOGLE_DRIVE_CLIENT_ID=xxx.apps.googleusercontent.com
#SECOND_GOOGLE_DRIVE_CLIENT_SECRET=xxx
#SECOND_GOOGLE_DRIVE_REFRESH_TOKEN=xxx
#SECOND_GOOGLE_DRIVE_FOLDER=backups
#SECOND_DRIVE_TEAM_DRIVE_ID=xxx
#SECOND_DRIVE_SHARED_FOLDER_ID=xxx

```

##### Add disks on `config/filesystems.php`

[](#add-disks-on-configfilesystemsphp)

```
'disks' => [
    // ...
    'google' => [
        'driver' => 'google',
        'clientId' => env('GOOGLE_DRIVE_CLIENT_ID'),
        'clientSecret' => env('GOOGLE_DRIVE_CLIENT_SECRET'),
        'refreshToken' => env('GOOGLE_DRIVE_REFRESH_TOKEN'),
        'folder' => env('GOOGLE_DRIVE_FOLDER'), // without folder is root of drive or team drive
        //'teamDriveId' => env('GOOGLE_DRIVE_TEAM_DRIVE_ID'),
        //'sharedFolderId' => env('GOOGLE_DRIVE_SHARED_FOLDER_ID'),
    ],
    // you can use more accounts, only add more disks and configs on .env
    // also you can use the same account and point to a diferent folders for each disk
    /*'second_google' => [
        'driver' => 'google',
        'clientId' => env('SECOND_GOOGLE_DRIVE_CLIENT_ID'),
        'clientSecret' => env('SECOND_GOOGLE_DRIVE_CLIENT_SECRET'),
        'refreshToken' => env('SECOND_GOOGLE_DRIVE_REFRESH_TOKEN'),
        'folder' => env('SECOND_GOOGLE_DRIVE_FOLDER'),
    ],*/
    // ...
],
```

##### Add driver storage in a `ServiceProvider` on path `app/Providers/`

[](#add-driver-storage-in-a-serviceprovider-on-path-appproviders)

Example:

```
namespace App\Providers;

use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider { // can be a custom ServiceProvider
    // ...
    public function boot(){
        // ...
        try {
            \Storage::extend('google', function($app, $config) {
                $options = [];

                if (!empty($config['teamDriveId'] ?? null)) {
                    $options['teamDriveId'] = $config['teamDriveId'];
                }

                if (!empty($config['sharedFolderId'] ?? null)) {
                    $options['sharedFolderId'] = $config['sharedFolderId'];
                }

                $client = new \Google\Client();
                $client->setClientId($config['clientId']);
                $client->setClientSecret($config['clientSecret']);
                $client->refreshToken($config['refreshToken']);

                $service = new \Google\Service\Drive($client);
                $adapter = new \Masbug\Flysystem\GoogleDriveAdapter($service, $config['folder'] ?? '/', $options);
                $driver = new \League\Flysystem\Filesystem($adapter);

                return new \Illuminate\Filesystem\FilesystemAdapter($driver, $adapter);
            });
        } catch(\Exception $e) {
            // your exception handling logic
        }
        // ...
    }
    // ...
}
```

Now you can access the drives like so:

```
$googleDisk = Storage::disk('google');
//$secondDisk = Storage::disk('second_google'); //others disks
```

Keep in mind that there can only be one default cloud storage drive, defined by `FILESYSTEM_CLOUD` in your `.env` (or config) file. If you set it to `google`, that will be the cloud drive:

```
Storage::cloud(); // refers to Storage::disk('google')
```

Limitations
-----------

[](#limitations)

Using display paths as identifiers for folders and files requires them to be unique. Unfortunately Google Drive allows users to create files and folders with same (displayed) names. In such cases when unique path cannot be determined this adapter chooses the oldest (first) instance. In case the newer duplicate is a folder and user puts a unique file or folder inside the adapter will be able to reach it properly (because full path is unique).

Concurrent use of same Google Drive might lead to unexpected problems due to heavy caching of file/folder identifiers and file objects.

Acknowledgements
----------------

[](#acknowledgements)

This adapter is based on wonderful [flysystem-google-drive](https://github.com/nao-pon/flysystem-google-drive) by Naoki Sawada.

It also contains an adaptation of [Google\_Http\_MediaFileUpload](https://github.com/googleapis/google-api-php-client/blob/master/src/Http/MediaFileUpload.php) by Google. I've added support for resumable uploads directly from streams (avoiding copying data to memory).

TeamDrive support was implemented by Maximilian Ruta - [Deltachaos](https://github.com/Deltachaos).

Adapter rewrite for Flysystem V2 and various fixes were implemented by Erik Niebla - [erikn69](https://github.com/erikn69).

###  Health Score

21

—

LowBetter than 19% of packages

Maintenance36

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity28

Early-stage or recently created project

 Bus Factor1

Top contributor holds 52.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

583d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/295817641b5f7842375c1c64a2c3cf4142679f1fbc27fac63e2a106a3076a804?d=identicon)[CodeIsArt](/maintainers/CodeIsArt)

---

Top Contributors

[![masbug](https://avatars.githubusercontent.com/u/11191264?v=4)](https://github.com/masbug "masbug (84 commits)")[![erikn69](https://avatars.githubusercontent.com/u/4933954?v=4)](https://github.com/erikn69 "erikn69 (48 commits)")[![Deltachaos](https://avatars.githubusercontent.com/u/679561?v=4)](https://github.com/Deltachaos "Deltachaos (4 commits)")[![elzdave](https://avatars.githubusercontent.com/u/36229438?v=4)](https://github.com/elzdave "elzdave (4 commits)")[![thotam](https://avatars.githubusercontent.com/u/78630736?v=4)](https://github.com/thotam "thotam (3 commits)")[![freimuts](https://avatars.githubusercontent.com/u/43796070?v=4)](https://github.com/freimuts "freimuts (3 commits)")[![mikemand](https://avatars.githubusercontent.com/u/745184?v=4)](https://github.com/mikemand "mikemand (3 commits)")[![Propaganistas](https://avatars.githubusercontent.com/u/6680176?v=4)](https://github.com/Propaganistas "Propaganistas (2 commits)")[![eusonlito](https://avatars.githubusercontent.com/u/644551?v=4)](https://github.com/eusonlito "eusonlito (2 commits)")[![StyleCIBot](https://avatars.githubusercontent.com/u/11048387?v=4)](https://github.com/StyleCIBot "StyleCIBot (2 commits)")[![felipeelia](https://avatars.githubusercontent.com/u/184628?v=4)](https://github.com/felipeelia "felipeelia (1 commits)")[![Cruiser13](https://avatars.githubusercontent.com/u/2771909?v=4)](https://github.com/Cruiser13 "Cruiser13 (1 commits)")[![Mark-H](https://avatars.githubusercontent.com/u/312944?v=4)](https://github.com/Mark-H "Mark-H (1 commits)")[![dragermrb](https://avatars.githubusercontent.com/u/11479696?v=4)](https://github.com/dragermrb "dragermrb (1 commits)")

---

Tags

Flysystemlaravelextendedgoogle-drivetranslated

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/realmatrix-flysystem-google-drive-ext/health.svg)

```
[![Health](https://phpackages.com/badges/realmatrix-flysystem-google-drive-ext/health.svg)](https://phpackages.com/packages/realmatrix-flysystem-google-drive-ext)
```

###  Alternatives

[masbug/flysystem-google-drive-ext

Flysystem adapter for Google Drive with seamless virtual&lt;=&gt;display path translation

2631.7M14](/packages/masbug-flysystem-google-drive-ext)[jerodev/flysystem-v3-smb-adapter

SMB adapter for Flysystem v3

1289.9k1](/packages/jerodev-flysystem-v3-smb-adapter)[private-it/flysystem-google-drive

FlySystem adapter for Google Drive (work with path)

207.8k](/packages/private-it-flysystem-google-drive)[quix-labs/laravel-supabase-flysystem

Supabase Adapter for Laravel Flysystem Storage

169.9k](/packages/quix-labs-laravel-supabase-flysystem)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
