Installation
composer require azure-oss/storage-blob
Add the package to providers in config/app.php if using Laravel’s service container:
'providers' => [
// ...
AzureOss\Storage\Blob\AzureStorageServiceProvider::class,
],
Configuration Publish the config file:
php artisan vendor:publish --provider="AzureOss\Storage\Blob\AzureStorageServiceProvider"
Update .env with your Azure Storage connection string:
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net
First Use Case Upload a file from Laravel’s public storage to Azure Blob Storage:
use AzureOss\Storage\Blob\BlobServiceClient;
use Illuminate\Support\Facades\Storage;
$service = BlobServiceClient::fromConnectionString(config('azure-storage.connection_string'));
$container = $service->getContainerClient('laravel-uploads');
$container->createIfNotExists();
$blob = $container->getBlobClient('user-uploads/' . uniqid() . '.jpg');
$blob->upload(
Storage::disk('public')->get('path/to/file.jpg'),
new UploadBlobOptions(contentType: 'image/jpeg')
);
File Uploads
$blob->upload(file_get_contents('local/path.jpg'));
$blob->upload($request->file('image')->get());
$blob->upload(
$content,
new UploadBlobOptions(
metadata: ['author' => 'John Doe'],
tags: ['category' => 'profile']
)
);
File Downloads
return response()->stream(
fn() => $blob->downloadStreaming()->content->detach(),
200,
['Content-Type' => 'application/pdf']
);
file_put_contents(
storage_path('app/downloads/' . $blobName),
$blob->downloadStreaming()->content->getContents()
);
Container Management
$blobs = $container->getBlobs(['maxResults' => 100]);
foreach ($blobs as $blob) {
// Process each blob
}
$container->setBlobServiceProperties([
'deleteRetentionPolicy' => new DeleteRetentionPolicy(7), // Days
'containerDeleteRetentionPolicy' => new DeleteRetentionPolicy(30),
]);
Shared Access Signatures (SAS)
$sasToken = $blob->generateSasToken(
new GenerateSasTokenOptions(
permissions: ['r'], // Read-only
expiresOn: now()->addHours(1)
)
);
$signedUrl = $blob->getUrl() . '?' . $sasToken;
<img src="{{ $signedUrl }}" alt="Azure Blob">
Integration with Laravel Filesystem
// config/filesystems.php
'disks' => [
'azure' => [
'driver' => 'azure',
'connection_string' => env('AZURE_STORAGE_CONNECTION_STRING'),
'container' => 'laravel-files',
],
],
Storage::disk('azure')->put('file.jpg', $content);
$content = Storage::disk('azure')->get('file.jpg');
Connection String Security
.env or connection strings to version control.env() helper or the config file for sensitive data.Large File Uploads
UploadBlobOptions with blockSize:
$blob->upload(
$content,
new UploadBlobOptions(blockSize: 10 * 1024 * 1024) // 10MB blocks
);
appendBlock().CORS Configuration
$container->setCors([
new CorsRule(
allowedOrigins: ['https://yourdomain.com'],
allowedMethods: ['GET', 'HEAD', 'PUT', 'POST', 'DELETE'],
allowedHeaders: ['*'],
exposedHeaders: ['Content-Type'],
maxAgeInSeconds: 86400
)
]);
Timeouts and Retries
'azure-storage' => [
'retry' => [
'max_retries' => 5,
'delay' => 2, // seconds
],
],
$service->setHttpClient(new \GuzzleHttp\Client([
'timeout' => 60,
]));
Blob Leasing
$lease = $blob->acquireLease(15); // 15-second lease
try {
$blob->upload($content);
} finally {
$lease->breakLease();
}
Enable Logging
Add to config/logging.php:
'channels' => [
'azure' => [
'driver' => 'single',
'path' => storage_path('logs/azure.log'),
'level' => 'debug',
],
],
Then enable in AzureStorageServiceProvider:
$this->app['log']->debug('Azure Blob operation', ['operation' => 'upload']);
Common Errors
StorageException: Check connection string, container name (must be lowercase), and permissions.404 Not Found: Verify blob/container exists and SAS tokens (if used) are valid.403 Forbidden: Ensure the storage account key or SAS token has correct permissions.Network Issues
AzureOss\Storage\Blob\Transport\AzureTransport with custom Guzzle middleware for retries:
$transport = new AzureTransport(
new \GuzzleHttp\Client([
'timeout' => 30,
'middleware' => [
new \GuzzleHttp\Middleware\RetryMiddleware([
'max_retries' => 3,
'retry_delay' => 100,
]),
],
])
);
$service->setTransport($transport);
Custom Metadata Handling
Extend UploadBlobOptions for project-specific metadata:
class CustomUploadOptions extends UploadBlobOptions {
public function __construct(
public string $userId,
public string $projectId,
array $metadata = []
) {
parent::__construct(metadata: array_merge($metadata, [
'user_id' => $userId,
'project_id' => $projectId,
]));
}
}
Event Listeners Listen for blob upload/download events (e.g., log or process files):
$blob->upload($content, new UploadBlobOptions())
->then(function () {
event(new BlobUploaded($blob->getName()));
});
Fluent Interface Chain operations for cleaner code:
$blob->upload($content)
->setMetadata(['custom_key' => 'value'])
->generateSasToken(new GenerateSasTokenOptions(permissions: ['r']))
->thenReturn($blob->getUrl());
Testing
Use the AzureOss\Storage\Blob\Mock\MockBlobServiceClient for unit tests:
$mockService = new MockBlobServiceClient();
$mockService->setMockResponse('hello.txt', 'Hello World');
$blob = $mockService->getContainerClient('test')->getBlobClient('hello.txt');
$this->
How can I help you explore Laravel packages today?