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

Ali Oss Storage Laravel Package

luoyy/ali-oss-storage

luoyy/ali-oss-storage adds a ready-to-use Alibaba Cloud OSS filesystem driver for Laravel, letting you store, retrieve, and serve files through OSS with familiar Storage API calls. Configure your bucket credentials and start uploading with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

luoyy/ali-oss-storage is a thin Laravel filesystem driver that registers an oss disk backed by Alibaba Cloud OSS. It's a community continuation of jacobcyl/ali-oss-storage now covering Laravel 10 through 13 (Laravel 13 support landed in v5.0.2), and the day-to-day mental model is: it's just a disk. If you know Storage::disk('local'), you know this package.

Minimal setup:

  1. Install the adapter (it pulls aliyuncs/oss-sdk-php transitively):
    composer require luoyy/ali-oss-storage
    
  2. Add credentials to .env:
    ALIYUN_OSS_ACCESS_KEY_ID=...
    ALIYUN_OSS_ACCESS_KEY_SECRET=...
    ALIYUN_OSS_BUCKET=my-bucket
    ALIYUN_OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
    ALIYUN_OSS_DOMAIN=              # optional CDN / custom domain
    ALIYUN_OSS_IS_CNAME=false
    
  3. Register a disk in config/filesystems.php:
    'oss' => [
        'driver'            => 'oss',
        'access_key_id'     => env('ALIYUN_OSS_ACCESS_KEY_ID'),
        'access_key_secret' => env('ALIYUN_OSS_ACCESS_KEY_SECRET'),
        'bucket'            => env('ALIYUN_OSS_BUCKET'),
        'endpoint'          => env('ALIYUN_OSS_ENDPOINT'),
        'domain'            => env('ALIYUN_OSS_DOMAIN'),
        'is_cname'          => env('ALIYUN_OSS_IS_CNAME', false),
    ],
    

Where to look first: the package is small — read src/ in the repo (Luoyy\AliOSS\AliOssAdapter and the service provider) before trusting your assumptions about which methods are implemented. It's faster than guessing from method signatures.

First use case — avatar upload returning a public URL:

$path = $request->file('avatar')->store('avatars', 'oss');
$url  = Storage::disk('oss')->url($path);

That's the whole happy path. Everything below is about making that predictable at scale.

Implementation Patterns

Keep the disk name as a variable, not a literal. The most common regression is tests or local dev writing to local while production writes to oss. Use config('filesystems.default') or a dedicated env (FILESYSTEM_DISK=oss), and reference Storage::disk($disk) everywhere. This one habit makes the driver switchable and testable.

Upload patterns by shape:

  • Small request-uploaded files: $request->file('x')->store('uploads/2024/06', 'oss')
  • Server-side content: Storage::disk('oss')->put('reports/foo.pdf', $contents)
  • Large / streaming (video, backups): ->writeStream($path, fopen($tmp, 'r')) — avoid put for anything over a few MB.
  • Directory-scoped: Storage::disk('oss')->makeDirectory($prefix) before bulk put calls; OSS is object-based, so this is a no-op for existence but keeps listing predictable.

Presigned URLs for private objects. The adapter version matters — verify temporaryUrl() in source before leaning on it. If it's not there, fall back to calling the Aliyun SDK directly through a small service class rather than forking the adapter. A single method:

app(AliyunOssClient::class)->signUrl($bucket, $key, $expires);

CDN / custom domain. Set domain to your CDN host (e.g. cdn.example.com) and is_cname => true when the bucket is bound to that domain. Storage::url() will then emit CDN URLs — this is the correct place to wire up image resizing or cache-busting, not in views.

Queues and jobs. Any upload over ~5 MB should be a job. Store the file to local first (or a temp stream), dispatch ProcessUpload, and let the worker call the OSS disk. This keeps web requests fast and retries OSS flakiness for free.

Directory convention matters more than you think. OSS listings are prefix-based and paginated at 1000 objects. A flat bucket with UUID filenames is fine; a bucket with million-key directories is not. Use tenant/{id}/, uploads/{Y}/{m}/, or similar so allFiles($prefix) stays bounded.

Testing. Storage::fake('oss') swaps the disk to a local temp filesystem — your tests never hit Aliyun. Add one integration test (marked @group slow) that actually round-trips put/get/url against a sandbox bucket, because fake() will not catch signature or domain misconfigurations. If you're upgrading to Laravel 13, run that integration test there specifically — the framework-version bump is the only thing v5.0.2 changed, so it's the only thing that could have regressed.

Gotchas and Tips

  • Endpoint format is unforgiving. Use the regional form oss-cn-hangzhou.aliyuncs.com, not the bucket-qualified my-bucket.oss-cn-hangzhou.aliyuncs.com and not the -internal variant unless you're inside the same VPC. Wrong endpoint → 301 Moved Permanently or SignatureDoesNotMatch.
  • domain + is_cname must agree. A CDN domain without is_cname produces 403s; a bucket-bound CNAME with a public domain produces signature errors. This is the #1 debugging trap. Reproduce with ossutil ls oss://bucket using the same credentials before blaming the package.
  • Bucket is private by default. storePublicly() and visibility => 'public' only work if the adapter forwards the header and the bucket ACL allows it. If public URLs 403, set the bucket ACL or use signed URLs — don't assume the driver wrote an ACL.
  • Overwriting an object doesn't invalidate the CDN. Same key, new content, stale URL. Use versioned keys (file-{uuid}.jpg) or call the CDN purge API.
  • url() behavior depends on config. No domain → the adapter reconstructs <bucket>.<endpoint>/<path>. With domain → that host is used verbatim. If URLs look wrong, this is why.
  • The driver name must be oss. It's whichever string the service provider registers via Storage::extend. Registering a disk with driver => 'aliyun' silently falls through to an InvalidArgumentException — check the provider source if you rename.
  • Large listings are paginated. allFiles($prefix) internally follows continuation tokens; on buckets with 100k+ objects this is slow and memory-hungry. Filter by prefix and date rather than listing everything.
  • Fork status. 14 stars, one maintainer, releases tied to Laravel version bumps (v5.0.1 → v5.0.2 is purely "Laravel 13 support"). Pin the version in composer.json ("luoyy/ali-oss-storage": "~5.0.2") and re-test after upgrades. If the fork goes quiet, Storage::extend('oss', fn () => ...) in your AppServiceProvider lets you ship your own adapter without forking — this is the cleanest escape hatch.
  • Debugging 403s: enable the Aliyun SDK's request log (a decorator around the OssClient) or set OSS_DEBUG=1 in a throwaway command. The error code (InvalidAccessKeyId, SignatureDoesNotMatch, NoSuchBucket) tells you exactly which config knob is wrong.
  • Path normalization. Leading / is stripped; backslashes are not. Build keys with implode('/', ...) and never with Windows-flavored helpers.
  • Timeouts on big uploads. The SDK uses Guzzle with a short default timeout. For multi-hundred-MB files, either use multipart upload (uploadFile, which the adapter may expose) or override the client timeout.
  • Laravel 13 is new, not battle-tested. v5.0.2's only change is framework compatibility, so if you're on Laravel 12 and stable, there's no functional reason to jump. Conversely, if you're moving to Laravel 13, this release finally unblocks you — but validate the Storage::extend registration and temporaryUrl on 13 in a staging run before trusting it in production.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core