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 Bundle Laravel Package

ticketpark/file-bundle

Ticketpark FileBundle is a Symfony bundle for handling file uploads and attaching files to Doctrine entities. It manages file storage and lifecycle, helping applications add reusable file management without writing custom upload logic.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — there is no service provider, no facade, no config publish. Treat it as a small library you either (a) use inside a Symfony app, or (b) mine for its two useful pieces: a remote-file cache and a download response.

First three steps

  1. Read composer.json before anything else. A 2016-12-24 release almost certainly pins symfony/http-foundation and symfony/filesystem to ~2.7|~3.0 and PHP >=5.5. On a modern Laravel app (Symfony 6/7 components, PHP 8.2) composer require ticketpark/file-bundle will fail dependency resolution. Expect to either fork/vendor the classes or reimplement.
  2. If you are on Symfony, look at Resources/config/services.yml first — that is where the service IDs live (typically a cache service and a response/download helper). Then read the DependencyInjection/Configuration.php for the cache directory and TTL knobs.
  3. Best first use case: caching a slow remote feed (supplier CSV, partner XML, generated PDFs/QR images) so your request path doesn't hit the network on every call, then serving the cached artifact through a download response.

Minimal Symfony wiring:

# config/packages/ticketpark_file.yaml
ticketpark_file:
    cache_dir: '%kernel.cache_dir%/file_cache'
    # lifetime / ttl keys vary by version — check Configuration.php
// Symfony controller
public function download(FileCache $cache): Response
{
    $path = $cache->get('https://partner.example/feed.csv', 3600);
    return new FileDownloadResponse($path, 'feed.csv');
}

If you are staying in Laravel, the realistic "getting started" is: copy the two or three real classes out of src/ into app/Support/FileCache/, drop the bundle plumbing, and bind them in a service provider. You keep the behaviour, you lose the dead dependency constraints.

Implementation Patterns

1. Cache-aside wrapper around remote fetches

The core value is path = f(url, ttl). Wrap it once and route every remote-fetch call site through it so TTL and cache location are centralised:

// app/Support/FileCache.php (reimplementation or vendored copy)
class FileCache
{
    public function __construct(private string $dir, private Http $http) {}

    public function get(string $url, int $ttl = 3600): string
    {
        $key  = hash('sha256', $url);
        $path = "{$this->dir}/{$key}";

        if (is_file($path) && filemtime($path) + $ttl > time()) {
            return $path;
        }

        $tmp = $path.'.'.bin2hex(random_bytes(6)).'.tmp';
        $this->http->timeout(30)->get($url)->throw()->body(); // stream to $tmp
        rename($tmp, $path); // atomic-ish swap
        return $path;
    }
}

2. Bind it as a singleton and inject it

In Laravel, register in a provider so the cache dir and TTL come from config/files.php, not from hardcoded strings scattered through controllers:

$this->app->singleton(FileCache::class, fn ($app) => new FileCache(
    storage_path('app/file-cache'),
    $app->make(\Illuminate\Http\Client\Factory::class),
));

3. Download endpoint pattern

Keep the download route dumb: resolve the cached path, then return a streamed response with an explicit filename and content type. Do not leak the on-disk path in headers.

Route::get('/feeds/{feed}', function (string $feed, FileCache $cache) {
    $path = $cache->get(config("feeds.urls.$feed"), 3600);
    return response()->streamDownload(fn () => readfile($path), "{$feed}.csv", [
        'Content-Type' => 'text/csv',
    ]);
})->middleware('auth');

4. Warm the cache off the request path

Remote fetches have tail latency and can fail. Schedule a feed:warm command every N minutes so the web request almost always hits a fresh file, and treat a cache miss as the slow path rather than the normal one. This is also where you notice the remote endpoint went down before your users do.

5. Integration tip — use it as a seam, not a framework

If you keep the Symfony classes, isolate them behind a one-method interface (FileCache::get) and never let FileDownloadResponse leak into your controllers. That way replacing the vendored 2016 code with Laravel's Storage + Http later is a one-file change.

Gotchas and Tips

  • Composer will fight you. The 2016 constraints will block installation against Laravel 10/11. Don't try to force it with --ignore-platform-reqs; you'll end up with two incompatible symfony/http-foundation copies. Fork the repo, loosen composer.json, or vendor the classes.
  • No service provider means no auto-discovery. In Laravel there is nothing to discover. Any "it's not registered" confusion is because there was never anything to register.
  • Cache directory must exist and be writable. The bundle usually writes to a configured path without creating it. Create it in a deploy step and fail loudly at boot if it isn't writable — a silent write failure degrades into "re-download every request," which looks like a remote-API problem, not a permissions problem.
  • Non-atomic writes are a real risk. If the original code writes directly to the final path, two concurrent requests can serve a truncated file. Always write to a temp file and rename() into place, and set the cache TTL from the file's mtime only after the rename.
  • Decide the failure policy explicitly. On a network error with a stale file present, you almost always want to serve the stale file and log, not throw. The default behaviour here is usually "throw," which turns a partner blip into a 500 for your users.
  • URL is an injection point if user-controlled. The cache key is the URL; if a user can supply it you've built an SSRF gadget. Allowlist hosts in config and never pass a raw request parameter into the cache lookup.
  • No timeouts, no retries, no tests. Assume the fetch layer has none. Set timeouts and a single retry yourself; add your own test around the TTL boundary (mtime + ttl == now) since none ship with the bundle.
  • Extension points are thin — lean on decoration. Rather than subclassing, decorate the cache service (CachingFileCache implements FileCacheInterface) to add metrics, logging, or a fallback-to-S3 path. In Symfony that's a decorates: entry; in Laravel it's a extend/bind wrapper.
  • Pin the exact commit if you vendor it. With 3 stars, no dependents, and no release since 2016, there is no maintenance path. Copy the file, add a header comment with the source URL and commit SHA, and own it from then on.
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