Have any questions:

Toll free:9801887718Available 24/7

Email our experts:info@mantraideas.com

In: Web Development

If you’re building a Laravel application that needs reliable cloud storage, learning how to upload files to Dropbox is one of the most practical skills you can add to your toolkit. Dropbox offers a robust API, generous storage limits, and excellent reliability — making it a strong choice for Laravel cloud storage needs.

In this tutorial, you’ll get a complete step-by-step guide on how to integrate the Dropbox API into your Laravel application, generate secure OAuth 2.0 tokens, configure a custom filesystem driver, and implement both upload and download services. By the end, you’ll have a fully working Laravel Dropbox integration ready for production.

Why Use Dropbox for Laravel File Storage?

Before jumping into the code, it’s worth understanding why Laravel cloud storage via Dropbox is a compelling choice for many teams:

  • Automatic token refresh — Unlike simple static API tokens, the OAuth 2.0 refresh token flow keeps your integration alive without manual intervention.
  • Production reliability — Dropbox’s infrastructure is battle-tested and suitable for handling real-world file upload workloads.
  • One-time authorization — You only need to go through the OAuth flow once; after that, Laravel handles token renewal automatically.
  • Familiar Laravel API — Once configured, you use the standard Storage facade, so your code stays clean and idiomatic.

Whether you’re storing user-uploaded documents, receipts, images, or any other file type, Dropbox file upload via Laravel is a seamless and maintainable solution.

Prerequisites

Before you begin, make sure you have:

  • A Laravel project (Laravel 9 or higher recommended)
  • A Dropbox account
  • Composer installed
  • Basic familiarity with Laravel’s filesystem and service providers

Step 1: Install the Required Package

composer require spatie/flysystem-dropbox

This package bridges the gap between Laravel’s Storage facade and the Dropbox API, giving you a clean interface for Laravel Dropbox filesystem operations.

Step 2: Create Your Dropbox App

To interact with the Dropbox API, you need to register an application in the Dropbox developer portal. 

  1. Visit https://www.dropbox.com/developers/apps
  2. Click Create App
  3. Choose:
    • Scoped Access
    • Full Dropbox or App Folder (your choice)
  4. Copy and Paste it in your .env File:
    • App Key
    • App Secret
    • Access Token 

Step 3: Generate Refresh Token

If you are working on development environment for upload/download into Dropbox, then generating the refresh token is not required. You can just use the access token generated from the earlier step and continue with the integration process. However, for production, the access token would not help since it will expire within 3 or 4 hours. Once it expires, every API call made by the application starts returning 401 unauthorized errors. The file upload and download breaks. And the only fix is to manually generate a new access token from the Dropbox developer portal, update the .env and run the application. This may work in development environment but for production, this is a serious reliability problem because the application silently fails for every user trying to upload or access file. 

Therefore, for production, generating the refresh token is crucial for Dropbox API Integration. Refresh token is a long-lived credential that never expires on its own (unless you revoke it.) The application uses it to programmatically request a new access token whenever the current one is about to expire. So there is no manual steps, no redeployments, and no downtime. 

Open the following URL in your browser

https://www.dropbox.com/oauth2/authorize?client_id=YOUR_APP_KEY&response_type=code&token_access_type=offline

Replace YOUR_APP_KEY with your actual app key.

  • Login to your Dropbox account when prompted
  • Authorize the app.
  • Copy the authorization code shown on the screen – it’s only valid for a short time.

Exchange the Code for Tokens

Run the following curl command in your terminal, substituting your actual values.

curl -X POST https://api.dropboxapi.com/oauth2/token \
  -d code=YOUR_CODE \
  -d grant_type=authorization_code \
  -d client_id=YOUR_APP_KEY \
  -d client_secret=YOUR_APP_SECRET

You will receive a JSON response like this:

{
  "access_token": "sl.xxxxx",
  "refresh_token": "slr.xxxxx",
  "expires_in": 14400
}

Store the refresh token in your .env. It does not expire (unless revoked), and your application will use it to request fresh access token automatically.

Add the following in your .env file:

DROPBOX_APP_KEY="YOUR_KEY"
DROPBOX_APP_SECRET="YOUR_SECRET_KEY"
DROPBOX_REFRESH_TOKEN="REFRESH_TOKEN"
DROPBOX_ACCESS_TOKEN=”ACCESS_TOKEN” #If not using refresh token

Step 4: Configure Dropbox Filesystem

Update config/filesystems.php

Add the following Dropbox disk configuration to the disks array

'dropbox' => [
    'driver' => 'dropbox',
],

Update config/services.php
Add your dropbox credentials to the services config so they can be accessed throughout the application.

'dropbox' => [
    'authorization_token' => env('DROPBOX_ACCESS_TOKEN'),
    'grant_type' => 'refresh_token',
    'client_id' => env('DROPBOX_APP_KEY'),
    'client_secret' => env('DROPBOX_APP_SECRET'),
     'refresh_token' => env('DROPBOX_REFRESH_TOKEN'),
],

Step 5: Create the DropboxServiceProvider

Since Dropbox is not a built-in Laravel filesystem driver, you need to register it as a custom driver via a service provider. This is crucial for Laravel Dropbox integration – it tells Laravel how to instantiate the Dropbox disk, including automatic token and refresh logic.

php artisan make:provider DropboxServiceProvider

Your DropboxServiceProvider will look like this:

<?php
namespace App\Providers;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client;
use Spatie\FlysystemDropbox\DropboxAdapter;

class DropboxServiceProvider extends ServiceProvider{
    public function boot(): void    {
        Storage::extend('dropbox', function ($app, $config) {
            $accessToken = Cache::remember('dropbox_access_token', 3500, function () {
                $response = Http::asForm()->post('https://api.dropboxapi.com/oauth2/token', [
                    'grant_type'    => config('services.dropbox.grant_type'),
                    'refresh_token' => config('services.dropbox.refresh_token'),
                    'client_id'     => config('services.dropbox.client_id'),
                    'client_secret' => config('services.dropbox.client_secret'),
                ]);
                return $response->json()['access_token'];
            });
            $client  = new Client($accessToken);
            $adapter = new DropboxAdapter($client);
            return new \Illuminate\Filesystem\FilesystemAdapter(
                new Filesystem($adapter, $config),
                $adapter,
                $config
            );
        });
    }
}

Register the Provider:

Add it to the providers array in config/app.php 

App\Providers\DropboxServiceProvider::class,

Step 6: Create a Path Helper

To keep file paths organized, create a DropboxPath helper class. This ensures consistent folder structure across your application.


This keeps uploads neatly organized by user, making retrieval straightforward and your Dropbox storage easy to browse.

<?php
namespace App\Helpers;
class DropboxPath
{
    public static function filePath($user, $filename): string
    {
        return "/{$user->id}/files/{$filename}";
    }
}

Step 7: Dropbox Service Class

For actual file upload and download, create a service class. Here, I have created two service classes for upload and download respectively. 

<?php

namespace App\Services\Dropbox;

use App\Exceptions\Dropbox\DropboxUploadFailedException;

use App\Helpers\DropboxPath;

use Illuminate\Support\Facades\Storage;

class UploadFileService

{

    /**

     * Upload a file to Dropbox.

     *

     * @throws DropboxUploadFailedException

     */

    public function upload($user, $file, $type=’id’): array

    {

        try {

            $filename = $type . '_' . time() . '.' . $file->getClientOriginalExtension();

            $path = DropboxPath::filePath($user, $filename);

            retry(3, function () use ($file, $path) {

                Storage::disk('dropbox')->put($path, file_get_contents($file));

            });

            return [

                'name' => $filename,

                'path' => $path,

            ];

        } catch (\Throwable $exception) {

            \Log::critical("Dropbox upload failed: " . $exception->getMessage());

            \Log::critical("Dropbox upload failed: " . $exception->getTraceAsString());

            throw new DropboxUploadFailedException("Couldn't upload file to Dropbox");

        }

    }

}

The UploadFileService class handles the file uploads to Dropbox. It is responsible for naming files, determining correct path, and pushing the file contents to Dropbox using Laravel’s Storage façade.

<?php

namespace App\Services\Dropbox;

use App\Exceptions\Dropbox\DropboxUploadFailedException;

use Illuminate\Support\Facades\Storage;

class DownloadFileService

{

    /**

     * Download a file from Dropbox.

     *

     * @throws DropboxUploadFailedException

     */

    public function download($path): string

    {

        try {

            return Storage::disk('dropbox')->get($path);

        } catch (\Throwable $exception) {

            \Log::critical("Dropbox download failed: " . $exception->getMessage());

            \Log::critical("Dropbox download failed: " . $exception->getTraceAsString());

            throw new DropboxUploadFailedException("Couldn't download file from Dropbox");

        }

    }

}

The DownloadFileService class is responsible for returning raw file contents which you can stream back to the browser, save locally, or process as needed.

Use these services in your controller to see the magic.

Conclusion:

You now have a complete, production-ready setup to upload files to Dropbox from your Laravel application. This integration covers everything from OAuth 2.0 token generation to custom filesystem drivers, organized path management, and robust error handling.

What makes this approach particularly powerful is the automatic token refresh via Laravel’s cache — once configured, your Dropbox API integration runs indefinitely without any manual intervention. The use of Laravel’s standard Storage facade also means this code is clean, testable, and easy for other developers on your team to understand.

Whether you’re building a document management system, a receipt tracker, or any application that requires Laravel cloud storage, this pattern scales well and keeps your file handling logic neatly encapsulated in dedicated service classes.

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *