Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Filesystem Oss Laravel Package

iidestiny/laravel-filesystem-oss

Aliyun OSS filesystem driver for Laravel, letting you use the Storage facade to upload, download, delete, and manage files on Alibaba Cloud Object Storage Service with support for custom domains, signed URLs, and streaming.

Deep Wiki
Context7

Getting Started

Install the driver and let Laravel auto-discover the service provider (Laravel 5.5+):

composer require iidestiny/laravel-filesystem-oss

On older Laravel, add Iidestiny\LaravelFilesystemOss\OssServiceProvider::class to config/app.php (check the README for the exact namespace in your major version).

Add a disk in config/filesystems.php:

'oss' => [
    'driver'      => 'oss',
    'access_id'   => env('OSS_ACCESS_ID'),
    'access_key'   => env('OSS_ACCESS_KEY'),
    'bucket'      => env('OSS_BUCKET'),
    'endpoint'    => env('OSS_ENDPOINT'),   // host only, e.g. oss-cn-hangzhou.aliyuncs.com
    'cdn_domain'  => env('OSS_CDN_DOMAIN'), // optional
    'ssl'         => true,
    'is_cname'    => false,
    'prefix'      => '',
    'options'     => [],
],

First use case — the 30-second smoke test:

Storage::disk('oss')->put('hello.txt', 'Hello OSS');
echo Storage::disk('oss')->url('hello.txt');

Where to look first:

  1. config/filesystems.php — confirm driver => oss and the endpoint/bucket.
  2. The package's OssAdapter for url(), temporaryUrl(), and how prefix/cdn_domain are applied. These drive 90% of day-to-day surprises.
  3. iidestiny/flysystem-oss (the underlying adapter) for OSS client options passed via the options array.

Implementation Patterns

Make OSS the default disk. Set 'default' => env('FILESYSTEM_DISK', 'oss') and use Storage::put/get/delete everywhere. Persist paths, not URLs, so CDN or endpoint changes don't invalidate the database.

Standard upload flow.

$path = $request->file('avatar')->store('avatars', 'oss'); // returns "avatars/uuid.ext"
// Later:
$url = Storage::disk('oss')->url($path);

Two disks for public vs private. Create oss-public (public-read bucket) and oss-private (default private ACL). Serve public assets with url(), and private files with temporaryUrl():

$signed = Storage::disk('oss-private')->temporaryUrl($path, now()->addMinutes(20));

CDN without losing the raw URL. cdn_domain rewrites every url() on that disk. If you need both, register two disks pointing at the same bucket — one with cdn_domain, one without.

Sandbox with prefix. Set 'prefix' => 'tenant-'.$tenant->id at runtime (via config([...]) before resolving the disk) to isolate tenants without tracking prefixes manually. Remember: paths you pass are relative; URLs include the prefix.

Streaming and large files. put() loads contents into memory. For uploads >10 MB use putFile, writeStream, or a queued job:

Storage::disk('oss')->writeStream("exports/{$id}.csv", $stream);

Image variants. Store the original, then build derived URLs yourself using OSS image processing (?x-oss-process=image/resize,w_400) rather than uploading every size. It keeps a single source of truth and cuts storage.

Direct browser uploads. The Laravel driver handles server-side I/O only. For direct-to-OSS uploads you need a signed POST policy — drop to OSS\OssClient for generatePostPolicy(), or hand-roll the policy and signature. Don't try to proxy multi-GB uploads through PHP.

Testing. Storage::fake('oss') swaps to a local disk, so path assertions work and no network is hit. It does not validate ACLs, signed URL correctness, or OSS error codes — cover those against a real test bucket in integration tests.

Migrating existing local files.

foreach (Storage::disk('local')->allFiles('uploads') as $file) {
    Storage::disk('oss')->writeStream($file, Storage::disk('local')->readStream($file));
}

Gotchas and Tips

  • Endpoint format. Pass the host only (oss-cn-hangzhou.aliyuncs.com), not https://.... If is_cname => true, supply your custom domain. A scheme in endpoint is the most common cause of SignatureDoesNotMatch / InvalidBucketName.
  • ssl => false produces http:// URLs. On an HTTPS app this triggers mixed-content blocks. Keep it true in production; the flag controls the synthesized URL scheme, not just the transport.
  • url() on a private bucket returns 403. Bucket ACL is configured in the OSS console, not by this package. Use temporaryUrl() for private objects or flip the bucket ACL.
  • Visibility options are best-effort. ['visibility' => 'public'] in put() may be ignored if the bucket blocks public ACLs. Verify in the console.
  • Wrong MIME type. OSS defaults to application/octet-stream for unknown extensions, causing browser downloads. Set content type explicitly: Storage::disk('oss')->put($path, $body, ['ContentType' => 'image/png']). OSS SDK option keys are ContentType, CacheControl, ContentDisposition.
  • Clock skew. Signed URLs fail with RequestTimeTooSkewed if the server's clock drifts. Keep NTP running; also remember OSS signs in UTC, so now()->addMinutes(10) is safe but hardcoded local dates are not.
  • Internal vs external endpoints. -internal.aliyuncs.com is faster/cheaper from ECS but produces URLs unreachable to the public. If your app runs in a VPC but serves browsers, use the public endpoint for the signing disk and the internal one only for server-to-server work — or sign on a public-endpoint disk.
  • temporaryUrl() needs Flysystem support. This package implements it, but the TTL is capped (usually 7 days on OSS). If you see UnableToGenerateTemporaryUrl, you're on an old major or a non-OSS disk.
  • Flysystem major versions. Laravel 9+ ships Flysystem 3 and expects a compatible release of this package. Mismatched pins produce Call to undefined method on the adapter. Check composer show iidestiny/flysystem-oss against your Laravel version before debugging deeper.
  • Directory deletes are recursive listings. Deleting a directory with thousands of objects is slow and can time out. Batch it or delete by prefix with the raw OSS client.
  • Config caching. After changing OSS credentials or the disk config, run php artisan config:clear — env() won't be re-read otherwise.
  • Non-ASCII and spaces in paths. url() does not always URL-encode. Slugify object keys (Str::slug() + hash) to avoid broken URLs and CDN cache misses.
  • Error codes are your friend. Catch League\Flysystem\UnableToWriteFile / UnableToReadFile and inspect $e->getPrevious()->getMessage() — it carries the OSS code (NoSuchKey, AccessDenied, SignatureDoesNotMatch), which tells you instantly whether it's config, IAM, or a missing object.
  • CORS. Browser direct uploads and loading fonts/CSS from OSS require a CORS rule on the bucket. Same origin policy bites silently until you add it.
  • Don't store signed URLs. Persist object paths; sign on read. Signed URLs expire and break every downstream cached page.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast