dscmall/laravel-filesystem-obs
A Laravel filesystem driver for Huawei Cloud OBS (Object Storage Service), letting you use OBS buckets through the familiar Storage facade. Drop-in Flysystem adapter supporting uploads, downloads, deletes and URLs alongside your existing disks.
Install the adapter and the underlying SDK — the package wraps Huawei's official obs/esdk-obs-php SDK, so pulling it in transitively is expected:
composer require dscmall/laravel-filesystem-obs
Laravel 5.5+ auto-discovers the service provider; on older apps add Dscmall\LaravelFilesystemObs\ObsServiceProvider::class to config/app.php.
Configure a disk in config/filesystems.php. The driver key is obs:
'disks' => [
'obs' => [
'driver' => 'obs',
'key' => env('OBS_ACCESS_KEY_ID'),
'secret' => env('OBS_SECRET_ACCESS_KEY'),
'bucket' => env('OBS_BUCKET'),
'endpoint' => env('OBS_ENDPOINT'), // e.g. https://obs.cn-north-4.myhuaweicloud.com
'domain' => env('OBS_DOMAIN'), // optional custom CDN domain
],
],
Set env vars in .env — the endpoint must be region-specific and host-only (no bucket prefix, no trailing slash).
First use case — treat it like any other disk:
Storage::disk('obs')->put('hello.txt', 'Hello OBS');
Storage::disk('obs')->exists('hello.txt'); // true
echo Storage::disk('obs')->url('hello.txt');
Where to look first — the ObsAdapter and ObsServiceProvider classes in the vendor directory. If a method (e.g. temporaryUrl, setVisibility) is missing you'll need to wrap the raw OBS client yourself.
As the default disk for user uploads. Point FILESYSTEM_DISK=obs and use the standard Storage facade everywhere. Controllers, form requests, and jobs stay disk-agnostic — swap back to local in tests.
Streaming large uploads. Use putFileAs / putFile with the uploaded file so Laravel streams via the SDK instead of reading into memory:
$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id . '.jpg', 'obs'
);
Signed URLs for private buckets. If the adapter implements temporaryUrl, generate short-lived links for downloads:
$url = Storage::disk('obs')->temporaryUrl('private/report.pdf', now()->addMinutes(10));
For long-lived assets, use a public bucket plus the domain config which points url() at your CDN (Huawei Cloud CDN or a custom domain bound to the bucket).
Spatie Media Library / Filament / Livewire uploads. Register obs as a filesystem disk in config/media-library.php / Filament's ->disk('obs'). Because these packages use the standard Storage facade, they generally work without modification — the main risk is signed URL support.
Multi-disk fallback strategy. Keep local as a scratch disk for processing (resizing images with Intervention, generating thumbnails) and push final artifacts to obs only:
$temp = Storage::disk('local')->path('tmp/' . $path);
Storage::disk('obs')->put($path, file_get_contents($temp), ['ACL' => 'public-read']);
Direct browser-to-OBS uploads. Skip the adapter for very large files — have the frontend POST directly to OBS using a pre-signed policy generated by the underlying ObsClient (createSignedUrl / createPostSignature), bypassing PHP entirely.
Testing. Never hit OBS in tests:
Storage::fake('obs');
This swaps in Laravel's in-memory disk and validates your code paths without network calls.
https://obs.<region>.myhuaweicloud.com exactly — a bucket name in the host, a missing scheme, or a trailing slash causes opaque signature errors. Check the Huawei Cloud console's bucket overview for the exact value.cn-north-4 won't answer a cn-south-1 endpoint; you'll get 301/403 responses that look like credential problems.url() will return a URL that 403s unless the object (or bucket) is public-read. Either set the ACL on upload via the options array (if supported) or configure the bucket policy externally.url() needs domain for CDN. Without a configured domain the adapter usually builds a virtual-hosted URL (https://<bucket>.<endpoint>/<path>), which works but is slow from outside mainland China and doesn't benefit from CDN caching.League\Flysystem\* exceptions. catch (League\Flysystem\UnableToWriteFile) may not fire; catch Obs\ObsException too if you need granular error handling.setVisibility. Pin the version in composer.json and re-test after any Laravel major upgrade.league/flysystem-aws-s3-v3 driver will authenticate against OBS unreliably. Use this package or the official SDK directly.(new \Obs\ObsClient([...]))->putObject(...) in tinker with the same credentials — if the raw SDK fails, the issue is config, not the package.ObsAdapter (or wrap the injected ObsClient) to add missing operations like temporaryUrl() or custom ACL handling, and register your subclass via Storage::extend('obs', ...) in a service provider.How can I help you explore Laravel packages today?