Jose Jimenez
Jose Jimenez
Software Architect & Developer
> >

Optimizing Spatie Media Library for Large Collections: A Custom Path Generator

Published in Laravel, PHP, Spatie on Feb 28, 2025

When working with Laravel applications that handle large media collections, Spatie's Media Library package is often the go-to solution. It provides a powerful and elegant way to manage files associated with your Eloquent models. However, as your application grows and the number of media files increases into the hundreds of thousands, you might encounter performance issues with the default file structure.

In this article, we'll explore a common challenge with large media collections and present a custom path generator solution that significantly improves file system management and performance.

The Problem: Flat Directory Structure

By default, Spatie's Media Library stores all files in a flat directory structure. Each media item gets its own directory named after its ID, but all these directories are stored in the same parent directory:

1/storage/app/public/media/1/
2/storage/app/public/media/2/
3/storage/app/public/media/3/
4...
5/storage/app/public/media/999999/

This approach works well for smaller applications, but when you're dealing with hundreds of thousands of files, this flat structure can cause several issues:

  1. File system limitations: Some file systems have performance issues when handling directories with an extremely large number of files/subdirectories.
  2. Slow directory listings: Operations that need to list directory contents become increasingly slow.
  3. Backup challenges: Backing up a directory with many thousands of entries can be problematic.

The Solution: A Custom Path Generator with Directory Sharding

To address these issues, we can implement a custom path generator that creates a hierarchical directory structure based on the media ID. This technique, often called "directory sharding," distributes files across multiple directories in a consistent and predictable way.

Our custom implementation uses an MD5 hash of the media ID to create a three-level directory structure, providing excellent distribution while keeping each directory at a manageable size.

Here's the custom path generator code:

 1<?php
 2 
3namespace App\Support\PathGenerator;
 4 
5use Spatie\MediaLibrary\MediaCollections\Models\Media;
6use Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator;
 7 
8class CustomPathGenerator extends DefaultPathGenerator
 9{
10 protected function getBasePath(Media $media): string
11 {
12 $prefix = config('media-library.prefix', '');
13 
14 // Adds a salt to the path to prevent guessable URLs
15 $hash = md5($media->getKey());
16 
17 // Create 3 levels of directories with 2 characters each
18 // This gives us 256 possible directories at each level (16^2)
19 // Which provides good distribution while keeping directory sizes manageable
20 $path = sprintf(
21 '%s/%s/%s/%s',
22 substr($hash, 0, 2),
23 substr($hash, 2, 2),
24 substr($hash, 4, 2),
25 $media->getKey()
26 );
27 
28 if ($prefix !== '') {
29 return $prefix.'/'.$path;
30 }
31 
32 return '/'.$path;
33 }
34}

How It Works

This solution works by:

  1. Generating an MD5 hash of the media ID, which provides a consistently distributed string regardless of the input pattern.
  2. Creating a hierarchical structure using the first 6 characters of the hash, broken into 2-character segments.
  3. Maintaining the original media ID at the end of the path for easy identification.

For example, media with ID 12345 might be stored at:

1/storage/app/public/media/a1/b2/c3/12345/

Benefits of This Approach

This custom path generator offers several advantages:

  1. Improved scalability: Each directory now contains a maximum of 256 subdirectories (16^2), regardless of how many media items you have.
  2. Better performance: Directory listing operations become much faster.
  3. Simplified backups: Backing up smaller, more manageable directories is more efficient.
  4. Enhanced security: The path includes an MD5 hash, making URLs less guessable.
  5. Backward compatibility: Existing code that uses the Media model remains unaffected.

Implementation in Your Laravel Application

To implement this solution:

1. Create the Custom Path Generator

Save the provided code to a file at app/Support/PathGenerator/CustomPathGenerator.php.

2. Configure Spatie Media Library

Update your config/media-library.php configuration file to use your custom path generator:

1'path_generator' => App\Support\PathGenerator\CustomPathGenerator::class,

3. Consider Migration for Existing Files

If you're implementing this in a project with existing media files, you'll need to migrate your files to the new structure. You can write a simple script that:

  1. Fetches all existing media records
  2. For each media item, generates the new path
  3. Moves the files to their new location
  4. Updates the media records if necessary

Considerations and Potential Modifications

While this solution works well for most use cases, you might want to consider these potential modifications:

  1. Adjust the number of directory levels based on your specific needs.
  2. Use a different hashing algorithm if MD5 doesn't meet your requirements.
  3. Add additional path components based on other attributes (like collection name or upload date).

Technical Deep Dive

Let's explore why this approach is so effective:

Distribution Analysis

With 2 characters per directory level and 16 possible hexadecimal characters (0-9, a-f), each level can have up to 256 different directories. With 3 levels, this gives us 256³ = 16,777,216 potential paths, ensuring that even with millions of files, each directory remains reasonably sized.

Conclusion

As your Laravel application grows, optimizing for scale becomes increasingly important. This custom path generator for Spatie's Media Library is a simple yet effective solution for managing large media collections without sacrificing the elegance and ease of use that the package is known for.

By implementing this directory sharding approach, you can ensure that your application continues to perform well even as your media collection grows to hundreds of thousands or even millions of files.