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

Storage File Share Laravel Package

azure-oss/storage-file-share

Laravel filesystem driver for Azure File Share. Integrates with the Storage facade so you can read, write, list, and delete files on Azure file shares through familiar Laravel APIs, with package config for quick setup in your app.

View on GitHub
Deep Wiki
Context7

Getting Started

This is the File Share half of a community-maintained Azure Storage SDK for PHP (AzureOss\Storage\File\Share), split out into its own repo. It talks to the Azure Files REST API — the same data that shows up on a VM as an SMB mount — rather than to Blob Storage. Think of it as "cheap POSIX-ish file storage with real directories," which is why it's usually the right answer for legacy line-of-business file shares, CAD/PDF/export dumps, and anything ops already mounts over SMB.

Install the split package (the split is what Composer resolves; the README, tests, and examples live in the parent monorepo, so open that first before reading source):

composer require azure-oss/storage-file-share

Then add a connection string to .env — grab it from the portal under Storage account → Security + networking → Access keys, and confirm it contains a FileEndpoint= entry, not just BlobEndpoint=:

AZURE_STORAGE_FILE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net
AZURE_STORAGE_FILE_SHARE=reports

The first use case to build is almost always a "drop a generated artifact somewhere a human or an SMB client can find it": render a PDF in a queued job, write it to tenant-42/invoices/2026-09.pdf, and let the finance team's mounted drive pick it up. That exercises auth, directory creation, and upload in about twenty lines, and it's the pattern you'll reuse for everything else.

Before writing code, read the client classes in src/ (FileShareClient, ShareClient, DirectoryClient, FileClient) — the object graph is client → share → directory → file, and getting that hierarchy into your head early saves a lot of flailing.

Implementation Patterns

Bind a singleton, don't new clients in controllers. There's no Laravel service provider in this package, so write your own:

// config/services.php
'azure_files' => [
    'connection_string' => env('AZURE_STORAGE_FILE_CONNECTION_STRING'),
    'share' => env('AZURE_STORAGE_FILE_SHARE', 'reports'),
],

// AppServiceProvider::register()
$this->app->singleton(FileShareClient::class, fn () => FileShareClient::fromConnectionString(
    config('services.azure_files.connection_string')
));

$this->app->singleton(ShareClient::class, fn ($app) => $app->make(FileShareClient::class)
    ->getShareClient(config('services.azure_files.share')));

Directory-per-tenant / per-domain. Because these are real directories, you can mirror your domain model into the path ({team}/{module}/{yyyy}/{mm}/{uuid}.pdf) and list a subtree cheaply. This is the big advantage over Blob Storage — a listFilesAndDirectories() on one directory is a natural, cheap "folder view," and an ops person can browse it over SMB with zero extra tooling.

Wrap it behind your own interface. Given the project's maturity signals (single-digit dependents, split repo, no Laravel integration), keep the SDK on one side of a boundary:

interface ReportArchive
{
    public function put(string $path, string $contents, array $metadata = []): void;
    public function stream(string $path);
    public function delete(string $path): void;
}

Then AzureFileShareArchive implements ReportArchive is the only file that imports AzureOss\.... Your tests get a trivial in-memory fake, and swapping to Blob/S3 later is a one-class change.

Large files: upload in ranges, don't buffer. Anything over a few megabytes should be streamed in chunks with explicit offsets. The File Share API expects you to declare the file's size before writing ranges, so the shape is: create the file at final size, then write range chunks. Do this inside a queued job with a bounded chunk size (4–8 MB is a sane default) so a 2 GB export doesn't blow memory_limit.

Download via a streamed response, not Storage::download:

return response()->streamDownload(function () use ($fileClient) {
    echo $fileClient->download()->getContent()->getContents();
}, 'invoice.pdf', ['Content-Type' => 'application/pdf']);

Lifecycle jobs. Pair the upload path with a scheduled prune command (files:prune --older-than=90d) that lists a directory and deletes by lastModified. Azure Files has no lifecycle-management rules like Blob does — retention is your job.

Metadata for app state. Store your own keys (tenant_id, job_id, checksum) on the file rather than a side table where reasonable; but see the caveats below on naming.

Gotchas and Tips

  • The split repo is source-only. No README, no tests, no examples. Always read the parent monorepo (php-oss-for-azure/azure-storage-*-php) for usage, and pin an exact version in composer.json — the split can drift in packaging even when the component API is stable.
  • This is not a Flysystem driver. There's no S3-compatible endpoint and no Storage::disk('azure-files'). Don't try to teach filesystems.php about it; treat it as a separate, deliberately-scoped service.
  • No local emulator. Azurite covers Blob/Queue/Table, not the File service. Plan on a real dev storage account (cheap) plus the interface wrapper above so your test suite never touches the network.
  • Share names are strict: 3–63 chars, lowercase letters/digits/hyphens only, no consecutive hyphens. Fail fast on boot rather than discovering it at 2 a.m.
  • The share and every intermediate directory must exist. There's no implicit mkdir -p; write an idempotent ensureDirectory($path) helper that walks the segments, and call it at the top of every write path.
  • Declare size before writing. createFile needs the final content length up front. Get this wrong and you'll see InvalidHeaderValue/OutOfRangeInput errors that read nothing like "you forgot the size."
  • No atomic rename or move. It's copy-then-delete, which means a window where both exist and no window where neither does. For "publish" semantics, write to tmp/ then copy to the final path.
  • Use If-Match / ETags for concurrent writers. Two jobs uploading the same logical file will silently last-writer-wins otherwise. If you need optimistic locking, read the ETag, pass it on write, and handle the 412.
  • Metadata keys are case-insensitive on the wire but round-trip in whatever case you sent — normalize to lowercase snake_case yourself or you'll chase "why is JobId missing" bugs.
  • Auth surface: connection string (account key) for server-side work; SAS URLs when you need to hand a time-limited link to a browser or a partner. Mint SAS server-side with a short TTL; never let a raw account key reach a client.
  • Errors are HTTP-shaped. Catch the SDK's exception types and map status codes — 404 (missing directory), 409 (ShareAlreadyExists, ParentNotFound), 412 (ETag mismatch), 403 (key/permission or IP firewall). A 403 that appears only in production is almost always the storage account firewall, not your code.
  • Throttling is real on large listings. Iterate with the continuation token rather than materializing everything; add jittered retry around listing and upload calls.
  • Extension points are thin. This is a low-level SDK, not a framework. Your leverage lives in the wrapper: retry policy, path builder, directory bootstrapping, and logging. Build those once and keep them out of the SDK's namespace.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console