alphasnow/aliyun-oss-appserver
Laravel package for Aliyun OSS direct uploads: it generates the upload policy and signature that web and mobile clients use to post files straight to OSS, keeping access keys server-side and taking upload bandwidth off your application.
This package wraps Aliyun OSS "app server" duties — primarily minting a signed upload policy so browsers/mobile clients can POST files directly to OSS without proxying bytes through your Laravel app. It's a thin, single-purpose library rather than a full OSS SDK, so expect to pair it with aliyuncs/oss-sdk-php (or plain HTTP calls) for anything beyond signing.
composer require alphasnow/aliyun-oss-appserver
php artisan vendor:publish --tag=aliyun-oss-appserver
config/aliyun-oss-appserver.php first — that's the map of everything the package can do. It holds the AccessKey pair, bucket, endpoint/host, an optional upload directory prefix, expiry window, and callback settings..env immediately (typically ALIYUN_OSS_ACCESS_KEY_ID, ALIYUN_OSS_ACCESS_KEY_SECRET, bucket/endpoint keys) and reference them from the config file. Never commit the published defaults with real keys.GET /api/oss/policy route that returns the signed policy payload as JSON, and a Vue/React/Blade form that POSTs key, policy, OSSAccessKeyId, signature, success_action_status, and the file straight to https://{bucket}.{endpoint}.If you only need to read/write objects from PHP, you don't need this package at all — use the official SDK. This one exists specifically for the browser-direct-upload flow.
Policy endpoint (the core pattern). Keep it behind auth middleware and derive the directory prefix from the authenticated user so tenants can't overwrite each other:
Route::get('/api/oss/policy', function () {
return response()->json(
AliyunOssAppServer::policy() // returns accessid, host, policy, signature, dir, expire, callback
);
});
The returned policy is a base64-encoded JSON document of conditions; signature is the HMAC-SHA1 of that base64 string keyed by your secret. The client must echo every condition back in the form exactly as specified or OSS rejects the POST with InvalidPolicyDocument.
Constrain uploads in the policy, not in PHP. The package's config usually lets you set conditions (max size, allowed Content-Type, starts-with on key). Do the hardening there — it's enforced by OSS itself, so it can't be bypassed by a client that edits the form. A size cap and a starts-with $key, "uploads/{userId}/" condition should be considered mandatory.
Callback handling. The usual flow sets an OSS callback so that after a successful upload OSS calls your Laravel endpoint with metadata (bucket, object, size, mimeType, custom callback-var). Treat that endpoint as unauthenticated-but-signed: verify the Authorization header OSS sends (it's an RSA signature over the callback body, verified with the OSS public key) before trusting the payload, then persist the file record. Don't use the browser's post-upload AJAX as the source of truth — it can lie, the callback can't.
Per-environment / multi-bucket. If you serve multiple buckets or regions, don't mutate the singleton at runtime. Either create a second config key and resolve a configured instance, or bind a small factory in a service provider that returns a clone with overridden options. Runtime config()->set() before calling the facade works but leaks across requests in Octane.
Frontend integration tips.
success_action_status: 200 (or 201) so OSS returns a clean response instead of a redirect.key field must match the policy's starts-with prefix; build it client-side as dir + uuid + ext.AllowedOrigin = your app domain, AllowedMethod = POST) or the browser upload fails with an opaque network error and no server-side log.Content-Type on the FormData part to match the policy condition; a mismatch is the single most common InvalidPolicyDocument cause.Testing. The signature is deterministic for a fixed policy and secret, so you can assert against a known-good fixture rather than hitting OSS. For end-to-end confidence, point a test bucket at your local callback route via a tunnel, or unit-test only the callback verifier with a captured header/body pair.
1.1.0 has no usable changelog. The release notes are only a compare link (1.0.0...1.1.0). Before bumping in production, read the diff on GitHub — for a signing library the risk surface is small, but a namespace/facade rename or a config key change would break you silently (facade resolution failures only surface at call time). Pin "alphasnow/aliyun-oss-appserver": "^1.1" and let CI catch it.host you sign for must be the bucket's actual regional endpoint (bucket.oss-cn-hangzhou.aliyuncs.com, not the global oss.aliyuncs.com). Signing against the wrong host produces a policy the browser accepts and OSS then rejects.accessid, never the secret. If you find yourself returning the secret to build the signature client-side, you've inverted the whole point of the package.php artisan config:cache in deploy scripts, and remember that any env() call outside the config file returns null once cached. All env reads belong in config/aliyun-oss-appserver.php.policy field, confirm the JSON conditions match the form fields one-for-one, confirm the signature is base64 of hash_hmac('sha1', $base64Policy, $secret, true), and confirm the OSSAccessKeyId matches the key that signed it. That covers ~95% of failures.auth middleware — OSS is the caller, not the user. Guard it with signature verification plus an idempotency key (the object key) instead.upload_max_filesize and post_max_size are irrelevant, while bucket-side limits and your policy conditions are the only guardrails. Don't assume Laravel validation is protecting you.sts:AssumeRole.How can I help you explore Laravel packages today?