spatie/dropbox-api
Minimal PHP client for Dropbox API v2 by Spatie. Provides core endpoints used by their Flysystem Dropbox adapter—create folders, list directories, fetch temporary links, and more. Easy to install via Composer and use with an auth token.
## Getting Started
### Minimal Setup
1. **Install the package**:
```bash
composer require spatie/dropbox-api
Obtain a Dropbox API token:
league/oauth2-client to handle token refreshes.Initialize the client:
use Spatie\Dropbox\Client;
$client = new Client($accessToken);
$client->upload('/path/to/file.txt', file_get_contents('local-file.txt'));
$contents = $client->listFolder('/dropbox-folder-path');
foreach ($contents as $item) {
echo $item['name'] . "\n";
}
$link = $client->getTemporaryLink('/path/to/file.txt');
Upload/Download:
// Upload from string
$client->upload('/remote/path/file.txt', 'file content');
// Upload from file resource
$client->upload('/remote/path/file.txt', fopen('local-file.txt', 'r'));
// Download to string
$content = $client->download('/remote/path/file.txt');
// Download to file
$client->download('/remote/path/file.txt', fopen('local-file.txt', 'w'));
Move/Rename:
$client->move('/old/path/file.txt', '/new/path/file.txt', autorename: true);
Delete:
$client->delete('/path/to/file.txt');
Create Folder:
$client->createFolder('/path/to/new-folder');
List Folder (with pagination):
$contents = $client->listFolder('/path/to/folder');
$nextBatch = $client->listFolderContinue($contents['cursor']);
Generate Temporary/Shared Links:
$tempLink = $client->getTemporaryLink('/path/to/file.txt');
$sharedLink = $client->createSharedLink('/path/to/file.txt');
List Shared Links:
$links = $client->listSharedLinks('/path/to/folder');
$results = $client->search('', 'query-term');
// config/services.php
'dropbox' => [
'token' => env('DROPBOX_ACCESS_TOKEN'),
'app_key' => env('DROPBOX_APP_KEY'),
'app_secret' => env('DROPBOX_APP_SECRET'),
],
// app/Providers/AppServiceProvider.php
use Spatie\Dropbox\Client;
public function register()
{
$this->app->singleton(Client::class, function ($app) {
$token = config('services.dropbox.token');
return new Client($token);
});
}
use Spatie\Dropbox\Client;
public function __construct(Client $dropbox)
{
$this->dropbox = $dropbox;
}
public function syncLocalToDropbox()
{
$this->dropbox->upload('/remote/path/file.txt', file_get_contents('local-file.txt'));
}
use Spatie\Dropbox\TokenProvider;
use League\OAuth2\Client\Provider\Dropbox as DropboxProvider;
class DropboxTokenProvider implements TokenProvider
{
public function __construct(private DropboxProvider $provider, private string $refreshToken)
{
}
public function getToken(): string
{
$token = $this->provider->getAccessToken('refresh_token', [
'refresh_token' => $this->refreshToken,
]);
return $token->getToken();
}
}
// Usage
$tokenProvider = new DropboxTokenProvider($oauthProvider, $refreshToken);
$client = new Client($tokenProvider);
// Start a session
$sessionId = $client->uploadSessionStart();
// Upload chunks
$client->uploadSessionAppend($sessionId, fopen('large-file.txt', 'r'));
// Finish upload
$client->uploadSessionFinish($sessionId, '/remote/path/large-file.txt');
// Direct RPC request
$response = $client->rpcEndpointRequest('files/get_metadata', [
'path' => '/path/to/file.txt',
]);
// Content endpoint request
$response = $client->contentEndpointRequest('files/download', [], fopen('local-file.txt', 'w'));
try {
$client->upload('/path/file.txt', 'content');
} catch (\Spatie\Dropbox\Exceptions\DropboxException $e) {
// Handle specific errors (e.g., path conflict)
if ($e->getErrorCode() === 'path/conflict') {
$client->upload('/path/file.txt', 'content', autorename: true);
}
}
Token Expiration:
TokenProvider for OAuth2 flows to handle refreshes.access_token_expired.Path Conflicts:
autorename: true in upload() or move() to avoid path/conflict errors.$client->upload('/path/file.txt', 'content', autorename: true);
Large File Uploads:
uploadSessionStart, uploadSessionAppend, uploadSessionFinish).Shared Link Settings:
createSharedLinkWithSettings may cause issues. Pass an empty array explicitly:
$client->createSharedLinkWithSettings('/path/file.txt', []);
Business Accounts:
namespace_id parameter:
$client->setNamespaceId('namespace-id');
Enable Guzzle Debugging: Add middleware to log requests/responses:
use GuzzleHttp\Middleware;
$stack = \GuzzleHttp\HandlerStack::create();
$stack->push(Middleware::tap(function ($request) {
\Log::debug('Dropbox Request:', [
'url' => (string) $request->getUri(),
'method' => $request->getMethod(),
'body' => (string) $request->getBody(),
]);
}));
$client = new Client($token, [], $stack);
Inspect Raw Responses:
Use rpcEndpointRequest or contentEndpointRequest to debug low-level API calls:
$response = $client->rpcEndpointRequest('files/get_metadata', ['path' => '/file.txt']);
\Log::debug('Raw Response:', $response);
Handle Rate Limits:
Dropbox may return 429 Too Many Requests. Retry with exponential backoff:
use GuzzleHttp\Exception\RequestException;
try {
$client->upload('/file.txt', 'content');
} catch (RequestException $e) {
if ($e->getCode() === 429) {
sleep(2); // Exponential backoff logic here
retry();
}
}
Subdomain Handling:
Prefix endpoints with subdomain:: for custom subdomains:
$client->rpcEndpointRequest('content::files/get_thumbnail_batch', $params);
Public Endpoints: Initialize the client without arguments for public access:
$client = new Client(); // Uses public API endpoints
App Authentication:
Use [appKey, appSecret] for app-level authentication (no user token required):
$client = new Client([$appKey, $appSecret]);
Custom HTTP Client: Replace the default Guzzle client by binding a custom instance:
$client = new Client($token, [], $customGuzzleClient);
Add New Methods:
Extend the Client class or use rpcEndpointRequest for unsupported endpoints:
// Example: Add a custom method
$client->rpcEndpointRequest('new/endpoint', ['param' => 'value']);
Event Listeners: Listen for Dropbox API events (e.g., file uploads) using Laravel's event system:
How can I help you explore Laravel packages today?