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

File Server Laravel Package

rekalogika/file-server

A file server for Laravel that streams files from local or remote storage through controlled HTTP endpoints, with access control, range requests, caching headers, and clean URLs. Deliver private downloads, images, and media without exposing storage paths.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install alongside the core file package. rekalogika/file-server is a companion to rekalogika/file (and almost certainly rekalogika/file-bundle / rekalogika/temporary-url). Install it with the rest of the stack, not in isolation:

    composer require rekalogika/file-server
    

    Because the package is a subtree split ([READ-ONLY]), pin to a known-good tag and expect the real docs to live in the monorepo, not in this repository's README.

  2. Confirm the bundle and routes. With Symfony Flex the bundle should auto-register in config/bundles.php. Check that the package ships a routing file and that it is loaded (either via Flex recipe or config/routes/rekalogika_file_server.yaml). If nothing is served, this is the first place to look.

  3. Find the config. Inspect vendor/rekalogika/file-server/ for DependencyInjection/Configuration.php and the bundle class. That file is the authoritative reference for the signing secret, default TTL, route prefix, and controller/service aliases — more reliable than any online doc for a 1-star package.

  4. First use case: hand out a temporary URL for a private file. The whole point of the package is to turn a FileInterface (stored outside the webroot, on S3, or in any storage adapter) into an HTTP URL the browser can fetch without exposing storage credentials:

    public function download(FileInterface $file, FileServerInterface $fileServer): JsonResponse
    {
        $url = $fileServer->createTemporaryUrl($file, new \DateInterval('PT15M'));
    
        return $this->json(['url' => (string) $url]);
    }
    

    Exact method names may differ — verify against vendor/ before committing to an interface in your own code.

Implementation Patterns

  • Service-generated URLs, not route-generated ones. Always go through the file-server service to mint a URL. Building the route yourself ($this->generateUrl('...')) skips the signature and will 403 at the resource controller.
  • Wrap behind your own port. Define a small FileUrlProvider interface in your domain and adapt the package service inside it. Given the package's maturity, this is cheap insurance if you need to swap it out later.
  • Expiry as a first-class parameter. Pass a DateInterval (or TTL seconds) at call time rather than relying on a global default. Different use cases want different windows: inline previews minutes, email links hours/days.
  • Twig integration. Expose a file_url(file, ttl) filter/twig extension that calls your provider. This keeps templates away from the package API and lets you add logging or metrics in one place.
  • Signed URL DTO. Return a small value object (url, expiresAt) from your provider so callers can put expiresAt in API responses and let clients refresh proactively.
  • Storage-agnostic flow. Treat the FileInterface as the input and the URL as the output. Your application code should not know or care whether the backing storage is local, S3, or something else — that's the value of layering this over rekalogika/file.
  • Refresh endpoint. Provide GET /files/{id}/url that remints a URL for an authenticated user; the browser calls it when a previously issued URL is close to expiry. This is the most common real-world pattern for long sessions.
  • Firewall boundary. The temporary-URL route is typically publicly reachable (signature is the auth), while the endpoint that mints URLs is behind your normal security.yaml firewall. Keep those two concerns in separate route prefixes.
  • Streamed responses. For large files, ensure the underlying response is a StreamedResponse / BinaryFileResponse from the file-server controller, not something your app buffers. If you need custom headers (Content-Disposition filename, cache-control), check whether the package exposes options or whether you need to wrap the response.

Gotchas and Tips

  • [READ-ONLY] is literal. Do not open issues or PRs against this repository; the canonical source is in the rekalogika/file monorepo. Any patches you make locally need to be reapplied after upgrades — prefer configuration over forking.
  • Signing secret must be stable and shared. If you run multiple app servers, all must use the same secret, or URLs minted on one node will fail on another. Rotate by supporting an old+new secret simultaneously if the bundle allows it; otherwise schedule a deploy that invalidates in-flight URLs.
  • Clock skew. Signature validation is time-based. If nodes drift, links randomly fail with 403s. Ensure NTP across app servers, and keep a small safety margin (don't mint 60-second URLs for email links).
  • Reverse proxies mangle signatures. A signature over the absolute URL breaks if nginx/Cloudflare rewrites host, scheme, or query ordering. Check whether the package signs the path+query only or the full URL. Terminate TLS at the proxy and make sure X-Forwarded-Proto/Host are trusted in Symfony, otherwise generated URLs will be http:// behind an https:// front end.
  • Query string caching. Some CDNs and proxy configs strip unknown query parameters. If your signature lives in the query string and the CDN strips it, every request 403s in production but works locally. Test through the real edge.
  • Don't put secrets in logs. Signed URLs are bearer credentials. Scrub them from access logs, Sentry breadcrumbs, and dump() output. Set short TTLs for anything that could end up pasted into chat.
  • Debugging a 403. Reduce to: (a) is the route reachable at all (404 vs 403)? (b) does the URL verify against the current secret on the same host? (c) has it expired? Log the reason the validator rejects (expired vs invalid signature vs missing secret) rather than a generic denial.
  • Content-Type and inline vs attachment. Serving user-uploaded files as text/html is an XSS vector. Prefer Content-Disposition: attachment for untrusted files, and set X-Content-Type-Options: nosniff. Check what the package sets by default and override only where you can prove it's safe.
  • Range requests. Video and PDF previews need HTTP Range support. Verify the response type supports it; a naive Response body will break scrubbing in media players.
  • Memory with large files. file_get_contents() on a 2 GB file will kill the request. Confirm the served response is streaming, and check PHP-FPM memory_limit and nginx proxy_buffering / fastcgi_buffering settings.
  • Cache headers. Temporary URLs should generally be Cache-Control: private, max-age=<short> or no-store. A public CDN caching a signed URL serves it to whoever asks — effectively bypassing expiry.
  • Extension points. The useful seams are usually: the URL generator/signer, the file resolver (how FileInterface is looked up from the URL), and the response factory. Register a decorator for those services in services.yaml rather than modifying vendor code.
  • Maturity reality check. With 1 star and no dependents, expect low bus factor. Keep the integration behind your own interface, pin the exact version in composer.json, add a smoke test that mints a URL and fetches it, and read the source before each upgrade.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core