hughcube/laravel-alioss
Laravel AliOSS
Alibaba Cloud OSS adapter for Laravel, based on alibabacloud/oss-v2.
Requirements
- PHP >= 8.0
- Laravel 9+
Installation
composer require hughcube/laravel-alioss
ServiceProvider auto-discovery is enabled. No manual registration needed.
Configuration
Add a disk to config/filesystems.php:
'disks' => [
'oss' => [
'driver' => 'alioss',
'bucket' => env('ALIOSS_BUCKET'),
'region' => env('ALIOSS_REGION', 'cn-shanghai'),
'accessKeyId' => env('ALIOSS_ACCESS_KEY_ID'),
'accessKeySecret' => env('ALIOSS_ACCESS_KEY_SECRET'),
'endpoint' => env('ALIOSS_ENDPOINT'), // optional
'prefix' => env('ALIOSS_PREFIX', ''), // optional
'internal' => env('ALIOSS_INTERNAL', false), // use internal endpoint
'isCName' => false, // optional
'securityToken' => null, // optional, STS token
'requestProxy' => null, // optional
'acl' => null, // optional, default ACL
'cdnBaseUrl' => env('ALIOSS_CDN_BASE_URL'), // optional
'uploadBaseUrl' => env('ALIOSS_UPLOAD_BASE_URL'), // optional
],
],
Quick Start
use HughCube\Laravel\AliOSS\AliOSS;
$adapter = AliOSS::getClient(); // or AliOSS::getClient('oss')
// Write
$adapter->write('path/file.txt', 'content');
// Read
$content = $adapter->read('path/file.txt');
// URL
$url = $adapter->cdnUrl('path/file.jpg');
echo $url; // https://cdn.example.com/path/file.jpg
Flysystem Operations
Standard FilesystemAdapter interface:
$adapter->write('file.txt', 'content');
$adapter->writeStream('file.txt', $stream);
$adapter->read('file.txt');
$adapter->readStream('file.txt');
$adapter->delete('file.txt');
$adapter->fileExists('file.txt');
$adapter->copy('source.txt', 'dest.txt');
$adapter->move('source.txt', 'dest.txt');
$adapter->createDirectory('dir');
$adapter->setVisibility('file.txt', 'public');
$adapter->visibility('file.txt');
$adapter->fileAttributes('file.txt');
Extended operations:
// Upload local file, returns OssUrl
$url = $adapter->writeFile('/tmp/photo.jpg', 'photos/photo.jpg');
// Download from URL and upload to OSS (stream, supports large files)
$url = $adapter->writeFromUrl('https://example.com/photo.jpg', 'photos/photo.jpg');
// Download to local file
$adapter->download('photos/photo.jpg', '/tmp/photo.jpg');
// Create symlink
$adapter->symlink('link.jpg', 'target.jpg');
// WeChat avatar scenario: upload only when URL changed
$url = $adapter->mirrorIfChanged($wechatAvatarUrl, $existingDbUrl, 'avatars');
URL Operations
All URL methods return OssUrl instances (extends HUrl, supports __toString).
Build URLs
$adapter->url('file.jpg'); // OSS URL (default)
$adapter->cdnUrl('file.jpg'); // CDN URL, null if not configured
$adapter->uploadUrl('file.jpg'); // Upload URL
$adapter->ossUrl('file.jpg'); // OSS external URL
$adapter->ossInternalUrl('file.jpg'); // OSS internal URL
$adapter->ossUri('file.jpg'); // oss://bucket/file.jpg
Signed URLs
$adapter->signUrl('file.jpg', 60); // GET signed, 60s
$adapter->signUploadUrl('file.jpg', 60); // PUT signed, 60s
$adapter->presign('file.jpg', 60, 'HEAD'); // PresignResult object
Domain Detection
$adapter->isCdnUrl($url);
$adapter->isUploadUrl($url);
$adapter->isOssUrl($url);
$adapter->isOssInternalUrl($url);
$adapter->isBucketUrl($url); // any of the above
Domain Conversion
$adapter->toCdnUrl($url);
$adapter->toUploadUrl($url);
$adapter->toOssUrl($url);
$adapter->toOssInternalUrl($url);
Parse URL
$ossUrl = $adapter->parseUrl('https://cdn.example.com/path/file.jpg');
OssUrl
OssUrl extends HUrl with OSS-specific capabilities. All methods are immutable (return new instances).
Domain Operations
$url = $adapter->cdnUrl('photo.jpg');
$url->toCdn(); // switch to CDN domain
$url->toUpload(); // switch to upload domain
$url->toOss(); // switch to OSS domain
$url->toOssInternal(); // switch to internal domain
$url->toOssUri(); // "oss://bucket/key"
$url->isCdn(); // true/false
$url->isUpload();
$url->isOss();
$url->isOssInternal();
$url->isBucket(); // any known domain
Signing
$url->sign(60); // GET signed URL
$url->sign(60, 'PUT'); // PUT signed URL
$url->sign(60, 'HEAD'); // HEAD signed URL
$url->signUpload(60); // shortcut for sign(60, 'PUT')
Process parameters are included in the signature automatically:
$adapter->ossUrl('photo.jpg')
->imageResize(800)
->imageFormat('webp')
->sign(300);
// x-oss-process is signed into the URL
Image Processing
Operations chain automatically. image/ prefix appears only once in the output.
$url = $adapter->cdnUrl('photo.jpg')
->imageResize(800, 600, 'fill')
->imageRotate(90)
->imageWatermarkText('Copyright', size: 30, color: 'FF0000')
->imageFormat('webp')
->imageQuality(85);
echo $url;
// https://cdn.example.com/photo.jpg?x-oss-process=image/resize,m_fill,w_800,h_600/rotate,90/watermark,.../format,webp/quality,q_85
| Method | Description |
|---|---|
imageResize($w, $h, $mode) |
Scale. Modes: lfit, mfit, fill, pad, fixed |
imageResizeByPercent($pct) |
Scale by percentage [1, 1000] |
imageCrop($w, $h, $gravity, $x, $y) |
Crop. Gravity: nw, north, ne, west, center, east, sw, south, se |
imageRotate($angle) |
Rotate [0, 360] |
imageFlip($dir) |
Flip: h, v, both |
imageFormat($fmt) |
Convert: jpg, png, webp, bmp, gif, tiff, heic, avif |
imageQuality($q, $abs) |
Quality [1, 100]. $abs=true for absolute |
imageBlur($r, $s) |
Blur. radius/sigma [1, 50] |
imageBright($val) |
Brightness [-100, 100] |
imageContrast($val) |
Contrast [-100, 100] |
imageSharpen($val) |
Sharpen [50, 399] |
imageCircle($r) |
Circle crop, radius [1, 4096] |
imageRoundedCorners($r) |
Rounded corners [1, 4096] |
imageAutoOrient() |
Auto-rotate by EXIF |
imageInterlace() |
Progressive display (JPG only) |
imageIndexCrop($size, $idx, $axis) |
Indexed slice |
imageWatermarkText($text, ...) |
Text watermark |
imageWatermarkImage($path, ...) |
Image watermark |
imageInfo() |
Image metadata (JSON) |
imageAverageHue() |
Dominant color |
Remove operations: imageRemoveResize(), imageRemoveRotate(), imageRemoveWatermark(), etc.
Video Processing
// Snapshot (sync)
$adapter->ossUrl('video.mp4')->videoSnapshot(1000, 800, 600);
// Video info (sync)
$adapter->ossUrl('video.mp4')->videoInfo();
// Transcode (async)
$adapter->ossUrl('video.mp4')
->videoConvert('mp4', 'h264', 'aac', '1280x720')
->saveas('bucket', 'output.mp4')
->notify('my-topic');
// GIF (async)
$adapter->ossUrl('video.mp4')->videoGif(5000, 3000, 320, 240);
// Sprite sheet (async)
$adapter->ossUrl('video.mp4')->videoSprite(5, 10, 10, 160, 90);
// Concat (async)
$adapter->ossUrl('video1.mp4')->videoConcat(['video2.mp4', 'video3.mp4']);
Audio Processing
$adapter->ossUrl('audio.mp3')->audioInfo();
$adapter->ossUrl('audio.wav')->audioConvert('mp3', 44100, 2, 320);
$adapter->ossUrl('audio1.mp3')->audioConcat(['audio2.mp3']);
Document Processing
$adapter->ossUrl('doc.docx')->docPreview();
$adapter->ossUrl('doc.docx')->docEdit();
$adapter->ossUrl('doc.docx')->docSnapshot(1);
$adapter->ossUrl('doc.docx')
->docConvert('pdf', 'docx', '1,2,4-10')
->saveas('bucket', 'output.pdf');
$adapter->ossUrl('doc.docx')->docTranslate('Hello', 'zh_CN');
Generic Process
$url->process('image/resize,w_800/rotate,90'); // sync
$url->asyncProcess('video/convert,f_mp4'); // async
$url->clearProcess(); // clear all
Validation Rule
OssFile validates that a URL points to a valid OSS file.
use HughCube\Laravel\AliOSS\Rules\OssFile;
$rules = [
'avatar' => [
'required',
OssFile::make()
->cdnDomain()
->image()
->maxSize(2 * 1024 * 1024)
->maxWidth(4096)
->maxHeight(4096)
->aspectRatio(1, 1),
],
'document' => [
'required',
OssFile::make()->anyDomain()->document()->maxSize(10 * 1024 * 1024),
],
'attachment' => [
'required',
OssFile::make()
->extensions(['pdf', 'docx', 'xlsx'])
->exceptExtensions(['exe', 'php'])
->directory('uploads')
->filenameMaxLength(100),
],
];
Constraints
Domain: cdnDomain(), uploadDomain(), ossDomain(), anyDomain()
File type: image(), video(), audio(), media(), document(), pdf(), word(), excel(), ppt(), archive(), text(), json(), xml(), mimeTypes([...])
Size: minSize($bytes), maxSize($bytes), sizeBetween($min, $max)
Image dimensions: maxWidth($px), maxHeight($px), aspectRatio($w, $h), minAspectRatio($w, $h), maxAspectRatio($w, $h)
Path: extensions([...]), exceptExtensions([...]), directory($dir), directories([...]), exceptDirectory($dir), filenameMaxLength($len)
Behavior: domainOnly(), checkExists(false)
Query After Validation
$rule->fileAttributes(); // FileAttributes
$rule->fileSize(); // ?int
$rule->mimeType(); // ?string
$rule->path(); // ?string
$rule->filename(); // ?string
$rule->extension(); // ?string
$rule->getDirectory(); // ?string
$rule->domainType(); // "cdn" | "upload" | "oss" | "oss_internal"
$rule->failedReason(); // failure code
License
MIT
Related Packages
Powerful PHP database abstraction layer (DBAL) with many features for database s...
Laravel Serializable Closure provides an easy and secure way to serialize closur...
Cli error handling for console/command-line PHP applications.