Looking to hire Laravel developers? Try LaraJobs

laravel-dms-disk maintained by arshad1114

Description
A custom Laravel filesystem disk driver for Document Management Services over HTTP.
Author
Last update
2026/03/16 07:47 (dev-main)
License
Links
Downloads
11

Comments
comments powered by Disqus

Laravel DMS Disk

Latest Version on Packagist Total Downloads License Try in Codespaces

A custom Laravel filesystem disk driver that lets any Laravel microservice store, retrieve and manage files on a remote Document Management Service (DMS) using the native Storage facade — no custom HTTP calls, no helper functions, no boilerplate.

Try it online — no install needed

Click the button above to launch a live demo in your browser using GitHub Codespaces. Both services start automatically — no setup required.

Once the Codespace loads:

bash .devcontainer/start.sh

Open a new terminal:

cd consumer-service && php artisan tinker

Then try:

Storage::disk('dms')->put('test/hello.txt', 'Hello World!');
Storage::disk('dms')->get('test/hello.txt');
Storage::disk('dms')->delete('test/hello.txt');

The problem

In a microservice architecture, when a service needs to store files on a dedicated DMS service, developers typically write custom HTTP calls in every service:

// ❌ what developers do today — repeated in every service
$response = Http::attach('file', $contents, 'invoice.pdf')
    ->post('https://dms.internal/upload', ['path' => 'invoices/001.pdf']);

The solution

Install this package and use the native Storage facade as you always have:

// ✅ with laravel-dms-disk
Storage::disk('dms')->put('invoices/001.pdf', $contents);
Storage::disk('dms')->get('invoices/001.pdf');
Storage::disk('dms')->delete('invoices/001.pdf');

The HTTP transport is completely invisible.

How it works

Consumer service                         DMS service
────────────────                         ───────────────────────────
Storage::disk('dms')->put(...)           Receives the HTTP request
       │                                 Calls Storage::put(...)
       │           HTTPS                 using its own
       └──────────────────────────────►  filesystems.php config

Requirements

  • PHP 8.1+
  • Laravel 10, 11, or 12

Installation

composer require arshad1114/laravel-dms-disk

The DmsServiceProvider is auto-discovered — no manual registration needed.

Publish the config:

php artisan vendor:publish --tag=dms-disk-config

Configuration

Add to your .env:

DMS_URL=https://your-dms-service.internal
DMS_TOKEN=your-strong-secret-token

Add the dms disk to config/filesystems.php:

'disks' => [
    // ... your existing disks

    'dms' => [
        'driver' => 'dms',
    ],
],

Disk selection

By default the DMS server uses its own configured default disk (FILESYSTEM_DISK in the DMS .env). You only need to set DMS_DISK if you want to target a specific disk on the DMS server:

# Use DMS server default disk — recommended
DMS_DISK=

# Or target a specific disk on the DMS server
DMS_DISK=client

You can also set it per disk in config/filesystems.php:

'dms' => [
    'driver' => 'dms',
    'disk'   => 'client',  // store on the client disk on the DMS server
],

Full config reference

All options in config/dms-disk.php:

Key Env variable Default Description
url DMS_URL '' Base URL of your DMS service
token DMS_TOKEN '' Bearer token for authentication
disk DMS_DISK null Disk name on the DMS server. If not set, DMS server uses its own default disk
timeout DMS_TIMEOUT 30 HTTP timeout in seconds
retry DMS_RETRY 3 Retry attempts on connection failure
retry_delay DMS_RETRY_DELAY 200 Milliseconds between retries

Multiple DMS disks

You can point multiple disks to different DMS services or different disks on the same DMS service:

'disks' => [
    // Uses DMS server default disk
    'dms' => [
        'driver' => 'dms',
        'url'    => env('DMS_URL'),
        'token'  => env('DMS_TOKEN'),
    ],

    // Targets the client disk on the DMS server
    'dms-client' => [
        'driver' => 'dms',
        'url'    => env('DMS_URL'),
        'token'  => env('DMS_TOKEN'),
        'disk'   => 'client',
    ],

    // Points to a completely different DMS service
    'dms-archive' => [
        'driver' => 'dms',
        'url'    => env('DMS_ARCHIVE_URL'),
        'token'  => env('DMS_ARCHIVE_TOKEN'),
    ],
],

Usage

Upload a file

// From a string
Storage::disk('dms')->put('invoices/001.pdf', $pdfContents);

// From an uploaded file in a controller
$request->file('document')->store('documents', 'dms');

// With a custom filename
$request->file('document')->storeAs('documents', 'invoice-001.pdf', 'dms');

// As public visibility
Storage::disk('dms')->put('avatars/user-1.jpg', $imageContents, 'public');

Download a file

// Get file contents as string
$contents = Storage::disk('dms')->get('invoices/001.pdf');

// Stream download directly to browser
return Storage::disk('dms')->download('invoices/001.pdf');

// Stream with custom filename
return Storage::disk('dms')->download('invoices/001.pdf', 'my-invoice.pdf');

Check existence

if (Storage::disk('dms')->exists('invoices/001.pdf')) {
    // file exists
}

if (Storage::disk('dms')->missing('invoices/001.pdf')) {
    // file does not exist
}

Delete a file

Storage::disk('dms')->delete('invoices/001.pdf');

Move and copy

// Move (rename)
Storage::disk('dms')->move('old/path.pdf', 'new/path.pdf');

// Copy
Storage::disk('dms')->copy('original.pdf', 'copy.pdf');

List files

// Files in a directory
$files = Storage::disk('dms')->files('invoices');

// Files recursively
$files = Storage::disk('dms')->allFiles('invoices');

File metadata

$size      = Storage::disk('dms')->size('invoices/001.pdf');
$mime      = Storage::disk('dms')->mimeType('invoices/001.pdf');
$timestamp = Storage::disk('dms')->lastModified('invoices/001.pdf');

URLs

// Public URL
$url = Storage::disk('dms')->url('avatars/user-1.jpg');

// Temporary signed URL
$url = Storage::disk('dms')->temporaryUrl('invoices/001.pdf', now()->addHour());

Visibility

Storage::disk('dms')->setVisibility('avatars/user-1.jpg', 'public');
Storage::disk('dms')->setVisibility('invoices/001.pdf', 'private');

$visibility = Storage::disk('dms')->visibility('avatars/user-1.jpg');
// returns 'public' or 'private'

Troubleshooting

401 Unauthorized

DMS_TOKEN in the consumer does not match DMS_SERVER_TOKEN in the DMS service. Make sure both values are identical.

Driver [dms] not supported

The dms disk is missing from config/filesystems.php. Add it as shown in the configuration section above.

Connection refused / timeout

DMS_URL is wrong or the DMS service is not running. Double check the URL and port.

Routes not found on DMS side

Run php artisan route:clear on the DMS service and check php artisan route:list --path=dms-disk.

File storing on wrong disk

If files are storing on the wrong disk on the DMS server, check DMS_DISK in your consumer .env. If it is set to local explicitly, clear it so the DMS server uses its own default:

DMS_DISK=

ServiceProvider not found

If you get Driver [dms] not supported, run:

php artisan package:discover
php artisan config:clear

If still not working, register the provider manually in bootstrap/providers.php (Laravel 11+):

Arshad1114\DmsDisk\Consumer\DmsServiceProvider::class,

Or in config/app.php (Laravel 10):

'providers' => [
    Arshad1114\DmsDisk\Consumer\DmsServiceProvider::class,
],

DMS server packages

Your DMS service can be written in any language that implements the API contract. Official server packages:

Framework Package
Laravel arshad1114/laravel-dms-disk-server
Node.js Coming soon

Contributing

Contributions are welcome. Please:

  1. Fork the repo
  2. Create a feature branch: git checkout -b feat/your-feature
  3. Write tests for your change
  4. Make sure all tests pass: ./vendor/bin/phpunit
  5. Open a pull request

License

MIT — see LICENSE file.