pimphand/gdrive
Composer 安装命令:
composer require pimphand/gdrive
包简介
Laravel Google Drive storage package with S3-style API, OAuth, streaming upload/download, and quota sync.
README 文档
README
Laravel package for using Google Drive as cloud storage with an S3-like API. Supports OAuth2, streaming uploads directly to Drive (without saving to local disk), download/preview with byte-range, and quota sync.
📖 Documentation: English / Indonesia (HTML) — PHP & JavaScript integration guide for new developers.
Features
- S3-style API —
put,get,delete,list,exists,url,quota - OAuth2 Google Drive — auth URL, exchange code, auto token refresh
- Streaming upload — files go directly to Google Drive without writing to server disk
- Streaming download — proxy files from Drive with
Rangeheader support - Google Workspace export — Docs/Sheets/Slides are automatically exported on download/preview
- App folder
pimpdrive— all physical files are stored in a root Drive folder (configurable) - Laravel auto-discovery — service provider & facade registered automatically
- Artisan commands —
gdrive:seed-config,gdrive:sync
Requirements
- PHP 8.2+
- Laravel 11, 12, or 13
- Google Cloud project with Google Drive API enabled
- Google OAuth Client ID & Secret
Installation
Via Packagist (production)
composer require pimphand/gdrive
Composer resolves and installs the latest stable release automatically (no version constraint needed).
Via path repository (local development)
Add to your Laravel project's composer.json:
{
"repositories": [
{
"type": "path",
"url": "../gdrive",
"options": {
"symlink": true
}
}
],
"require": {
"pimphand/gdrive": "@dev"
}
}
Then run:
composer require pimphand/gdrive:@dev
Publish config (optional)
php artisan vendor:publish --tag=gdrive-config
The config file will be available at config/gdrive.php. Without publishing, the package's default config is merged automatically.
Publish full example app (recommended for first-time setup)
This single command creates controllers, routes, views, and a token store — immediately accessible at /gdrive:
php artisan vendor:publish --tag=gdrive-example
Updating stubs after a package upgrade — vendor:publish does not overwrite existing files. Use one of:
php artisan vendor:publish --tag=gdrive-example --force
# or (always overwrites with the latest version from the package)
php artisan gdrive:publish-example
Files created automatically:
| File | Purpose |
|---|---|
routes/gdrive.php |
/gdrive routes (auto-loaded by the package) |
app/Http/Controllers/GDrive/GDriveController.php |
Dashboard, upload, download, preview, delete |
app/Http/Controllers/GDrive/GDriveAuthController.php |
OAuth connect / callback / disconnect |
app/Http/Controllers/GDrive/GDriveApiController.php |
Chunk upload API + sync |
app/Services/GDrive/FileGoogleDriveTokenStore.php |
Store encrypted tokens in storage/app/gdrive/ |
resources/views/gdrive/*.blade.php |
Demo pages |
public/js/gdrive-demo.js |
Direct upload to Drive + sync |
public/css/gdrive-drive.css |
Demo styles |
config/gdrive.php |
Package configuration |
gdrive.env.example |
.env variable template |
No need to edit routes/web.php — the package automatically loads routes/gdrive.php if that file exists.
Quick setup (.env only)
- Publish the example (see above)
- Copy variables from
gdrive.env.exampleto.env:
GDRIVE_CLIENT_ID=your-client-id.apps.googleusercontent.com GDRIVE_CLIENT_SECRET=your-client-secret GDRIVE_REDIRECT_URI=http://localhost:8000/auth/google/callback
- In Google Cloud Console, add the redirect URI:
http://localhost:8000/auth/google/callback - Start the server:
php artisan serve
- Open http://localhost:8000/gdrive → click Connect Google Drive
Example routes
| Method | URL | Purpose |
|---|---|---|
| GET | /gdrive |
Dashboard (quota, file list, upload) |
| GET | /gdrive/connect |
Start Google OAuth |
| GET | /gdrive/callback |
OAuth callback |
| POST | /gdrive/disconnect |
Disconnect Drive |
| POST | /gdrive/upload |
Upload file |
| GET | /gdrive/files/{id}/download |
Download file |
| GET | /gdrive/files/{id}/preview |
Inline preview |
| DELETE | /gdrive/files/{id} |
Delete file |
Google Cloud Configuration
- Open Google Cloud Console
- Create a project (or use an existing one)
- Enable Google Drive API
- Create an OAuth 2.0 Client ID (type: Web application)
- Add Authorized redirect URIs, for example:
http://localhost:8000/auth/google/callbackhttps://yourdomain.com/auth/google/callback
Environment Variables
Add to your Laravel project's .env:
# OAuth client (required) GDRIVE_CLIENT_ID=your-client-id.apps.googleusercontent.com GDRIVE_CLIENT_SECRET=your-client-secret GDRIVE_REDIRECT_URI=http://localhost:8000/auth/google/callback # Root folder name in Google Drive (default: pimpdrive) GDRIVE_APP_FOLDER=pimpdrive # Token encryption key (use a long random string) GDRIVE_TOKEN_ENCRYPTION_KEY=your-random-secret-key # OAuth tokens for the connected account (after OAuth flow) GDRIVE_ACCESS_TOKEN=ya29.... GDRIVE_REFRESH_TOKEN=1//0g.... GDRIVE_TOKEN_EXPIRES_AT=2026-06-07T12:00:00+00:00
Config validation
php artisan gdrive:seed-config
# Show encrypted values (for database seeding)
php artisan gdrive:seed-config --show-encrypted
Basic Usage
Facade (simplest)
use Pimphand\GDrive\Facades\GDrive; // Upload file $file = GDrive::put( fileName: 'report.pdf', body: $request->getContent(), // string, resource, or StreamInterface mimeType: 'application/pdf', sizeBytes: (string) $request->header('Content-Length'), // optional ); // Response: ['id' => '...', 'name' => '...', 'mime_type' => '...', 'size' => '...'] // Download (returns StreamedResponse) return GDrive::get($file['id']); // Inline preview (video/PDF in browser) return GDrive::get($file['id'], disposition: 'inline'); // Byte-range (video seek) return GDrive::get($file['id'], range: $request->header('Range')); // Delete file GDrive::delete($file['id']); // List all files in the app folder $files = GDrive::list(); // Check if file exists GDrive::exists($file['id']); // Google Drive web view URL $viewUrl = GDrive::url($file['id']); // Sync quota $quota = GDrive::quota();
Dependency Injection
use Pimphand\GDrive\GoogleDriveStorage; class FileController extends Controller { public function __construct( private readonly GoogleDriveStorage $storage, ) {} public function upload(Request $request) { $file = $this->storage->put( $request->file('file')->getClientOriginalName(), fopen($request->file('file')->getRealPath(), 'r'), $request->file('file')->getMimeType(), (string) $request->file('file')->getSize(), ); return response()->json($file); } public function download(string $fileId) { return $this->storage->get($fileId); } }
Static factory
use Pimphand\GDrive\GoogleDriveStorage; $storage = GoogleDriveStorage::fromConfig(); $file = $storage->put('photo.jpg', file_get_contents('/path/to/photo.jpg'), 'image/jpeg');
Upload Controller (full example)
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Pimphand\GDrive\Facades\GDrive; class UploadController extends Controller { public function store(Request $request) { $request->validate([ 'file' => ['required', 'file', 'max:512000'], // max 500MB ]); $uploaded = $request->file('file'); $file = GDrive::put( fileName: $uploaded->getClientOriginalName(), body: fopen($uploaded->getRealPath(), 'r'), mimeType: $uploaded->getMimeType() ?? 'application/octet-stream', sizeBytes: (string) $uploaded->getSize(), ); // Save $file['id'] to your application database return response()->json([ 'provider_file_id' => $file['id'], 'name' => $file['name'], 'mime_type' => $file['mime_type'], 'size' => $file['size'], ], 201); } }
OAuth Flow (example)
The package provides OAuth helpers in GoogleDriveService. Simple route example:
// routes/web.php use Illuminate\Support\Facades\Route; use Pimphand\GDrive\Facades\GDrive; use Pimphand\GDrive\GoogleDriveService; use Pimphand\GDrive\TokenCrypto; Route::get('/auth/google', function (GoogleDriveService $drive) { $state = TokenCrypto::fromConfig()->randomToken(); session(['google_oauth_state' => $state]); return redirect($drive->getAuthUrl($state)); }); Route::get('/auth/google/callback', function (GoogleDriveService $drive, Request $request) { if ($request->query('state') !== session('google_oauth_state')) { abort(403, 'Invalid OAuth state.'); } $credentials = $drive->exchangeAuthCode($request->query('code')); // Save $credentials to database (use toEncrypted() for encryption) $encrypted = $credentials->toEncrypted(); // ... persist to your ConnectedAccount model return redirect('/dashboard')->with('success', 'Google Drive connected.'); });
Custom Token Store (multi-account)
For applications with multiple Google Drive accounts, implement GoogleDriveTokenStore:
<?php namespace App\Services; use App\Models\ConnectedAccount; use DateTimeInterface; use Pimphand\GDrive\Contracts\GoogleDriveTokenStore; use Pimphand\GDrive\GoogleDriveCredentials; class DatabaseGoogleDriveTokenStore implements GoogleDriveTokenStore { public function __construct( private readonly ConnectedAccount $account, ) {} public function getCredentials(): GoogleDriveCredentials { return GoogleDriveCredentials::fromEncrypted( $this->account->access_token_encrypted, $this->account->refresh_token_encrypted, $this->account->token_expires_at, ); } public function saveAccessToken(string $accessToken, DateTimeInterface $expiresAt): void { $crypto = app(\Pimphand\GDrive\TokenCrypto::class); $this->account->update([ 'access_token_encrypted' => $crypto->encrypt($accessToken), 'token_expires_at' => $expiresAt, ]); } }
Use with the service directly:
use Pimphand\GDrive\GoogleDriveStorage; use App\Services\DatabaseGoogleDriveTokenStore; $account = ConnectedAccount::findOrFail($id); $storage = GoogleDriveStorage::fromConfig(new DatabaseGoogleDriveTokenStore($account)); $file = $storage->put('backup.zip', fopen('php://input', 'r'), 'application/zip');
Or bind globally in AppServiceProvider:
use Pimphand\GDrive\Contracts\GoogleDriveTokenStore; use App\Services\DatabaseGoogleDriveTokenStore; // config/gdrive.php 'token_store' => DatabaseGoogleDriveTokenStore::class,
Sync Files from Drive
The package provides reconcile logic:
use Pimphand\GDrive\Facades\GDrive; // Fetch local records from database, keyed by provider_file_id $existing = File::where('user_id', $userId) ->get() ->keyBy('provider_file_id') ->map(fn ($f) => [ 'id' => $f->provider_file_id, 'name' => $f->name, 'mime_type' => $f->mime_type, 'size' => (string) $f->size_bytes, 'status' => $f->status, ]) ->all(); $result = GDrive::drive()->syncAppFolderFiles($existing); // $result = ['created' => 2, 'updated' => 1, 'deleted' => 0, 'files' => [...]] foreach ($result['files'] as $change) { match ($change['action']) { 'create' => File::create([...]), 'update' => File::where('provider_file_id', $change['id'])->update([...]), 'delete' => File::where('provider_file_id', $change['id'])->update(['status' => 'deleted']), }; }
Artisan sync
php artisan gdrive:sync
Displays quota and the file list in the Drive app folder.
API Reference
GoogleDriveStorage (S3-style)
| Method | Description | Return |
|---|---|---|
put($name, $body, $mime, $size?) |
Upload to app folder | array{id, name, mime_type, size} |
get($id, $range?, $disposition?) |
Stream download/preview | StreamedResponse |
delete($id) |
Delete file on Drive | void |
exists($id) |
Check if file exists | bool |
list() |
List files in app folder | array[] |
url($id) |
Google web view URL | ?string |
quota() |
Sync & return quota | array |
drive() |
Access low-level service | GoogleDriveService |
GoogleDriveService (low-level)
| Method | Description |
|---|---|
getAuthUrl($state) |
Generate OAuth authorization URL |
exchangeAuthCode($code) |
Exchange auth code → credentials |
ensureAppFolder() |
Get/create root app folder |
upload(...) |
Upload file |
rename($id, $name) |
Rename on Drive |
delete($id) |
Delete on Drive |
getMetadata($id) |
Fetch file metadata |
listAppFolderFiles() |
List all files in app folder |
syncAppFolderFiles($existing) |
Reconcile with local records |
syncQuota() |
Fetch storage quota from Drive API |
TokenCrypto
| Method | Description |
|---|---|
encrypt($value) |
AES-256-GCM encrypt |
decrypt($value) |
AES-256-GCM decrypt |
randomToken($bytes?) |
Generate random URL-safe token |
hashToken($token) |
SHA-256 hash |
Architecture
Laravel App
│
├── GDrive Facade / GoogleDriveStorage
│ ├── put() ──► GoogleDriveService::upload()
│ ├── get() ──► GoogleDriveStreamService::stream()
│ └── quota() ──► GoogleDriveService::syncQuota()
│
├── GoogleDriveTokenStore (interface)
│ └── EnvGoogleDriveTokenStore (default, from .env)
│
└── Google Drive API
└── /root/pimpdrive/ ← all physical files are stored here
Important: Virtual folders (file organization in your app) are database metadata only — they are not mirrored in the Google Drive folder structure. All physical files live in a single root pimpdrive folder per Google account.
Publishing to Packagist
- Push the package to the GitHub repository
pimphand/gdrive - Create a release / semver tag (e.g.
v1.0.0) - Submit to Packagist.org
- Install in other projects:
composer require pimphand/gdrive
Security
- Do not commit
.envor tokens to the repository - Store refresh tokens encrypted in the database (use
TokenCrypto) - Use the OAuth
stateparameter for CSRF protection - Do not log access tokens, refresh tokens, or client secrets
- Always stream uploads directly to Drive — do not write uploaded files to server disk
License
MIT License — see LICENSE.
Contributing
Pull requests are welcome. For major changes, please open an issue first.
pimphand/gdrive 适用场景与选型建议
pimphand/gdrive 是一款 基于 JavaScript 开发的 Composer 扩展包,目前已累计 7 次下载、GitHub Stars 达 2, 最近一次更新时间为 2026 年 06 月 08 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「storage」 「s3」 「oauth」 「google」 「laravel」 「Flysystem」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 pimphand/gdrive 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 pimphand/gdrive 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 pimphand/gdrive 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A SDK for working with B2 cloud storage.
Small library to access Microsoft Windows Azure Blob Storage with a Service or a StreamWrapper.
WeChat OAuth SDK
Ory-Hydra OAuth 2.0 Client Provider for The PHP League OAuth2-Client
Library for ORCID web services
A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.
统计信息
- 总下载量: 7
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 36
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-08