PHPackages                             hasanhawary/media-manager - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. hasanhawary/media-manager

ActiveLibrary[File &amp; Storage](/categories/file-storage)

hasanhawary/media-manager
=========================

Flexible Laravel media manager: accept media from UploadedFile, base64, URLs, or local paths and store on any filesystem disk.

1.5.1(4w ago)15061MITPHPPHP &gt;=8.1 &lt;8.6CI failing

Since Sep 20Pushed 3w agoCompare

[ Source](https://github.com/hasanhawary/media-manager)[ Packagist](https://packagist.org/packages/hasanhawary/media-manager)[ Docs](https://github.com/hasanhawary/media-manager)[ RSS](/packages/hasanhawary-media-manager/feed)WikiDiscussions main Synced 2d ago

READMEChangelogDependencies (12)Versions (14)Used By (1)

Media Manager
=============

[](#media-manager)

[![Latest Stable Version](https://camo.githubusercontent.com/b21cbd7c3d0c330f201fe8e7730ef84da12a9899ee7abf9a4096804e3fbbe0af/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f686173616e6861776172792f6d656469612d6d616e616765722e737667)](https://packagist.org/packages/hasanhawary/media-manager)[![Total Downloads](https://camo.githubusercontent.com/b3bf8f1b6a138fe0a52cc7523071ff8a4f023db749bef09b374c3dcc1d7a0edb/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f686173616e6861776172792f6d656469612d6d616e616765722e737667)](https://packagist.org/packages/hasanhawary/media-manager)[![PHP Version](https://camo.githubusercontent.com/f2aed7f9fd1e1dc13489ffd5fe580a8d36a0a2c535f90f37806e54582cd4fdfd/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f686173616e6861776172792f6d656469612d6d616e616765722e737667)](https://packagist.org/packages/hasanhawary/media-manager)[![Tests](https://github.com/hasanhawary/media-manager/actions/workflows/tests.yml/badge.svg)](https://github.com/hasanhawary/media-manager/actions/workflows/tests.yml)[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)

Media Manager is a reusable Laravel package for storing files from uploaded files, base64 strings, remote URLs, raw content, and local paths. It supports disk selection, naming strategies, replacement flows, chunked uploads, URL generation, metadata, delete, and safe delete.

The package is self-contained and does not depend on a host app namespace such as `App\...`.

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10, 11, 12, or 13
- Configured Laravel filesystem disks

Some low-level helpers such as `PathNormalizer`, `FileNameGenerator`, and `RemoteMediaFetcher` can be used in plain PHP. Storage, facades, `UploadedFile`, URL generation, metadata, and chunk uploads are Laravel filesystem features.

Installation
------------

[](#installation)

```
composer require hasanhawary/media-manager
```

Laravel discovers the service provider and facade alias automatically:

```
use HasanHawary\MediaManager\Facades\Media;
```

Publish the optional config file:

```
php artisan vendor:publish --tag=media-manager-config
```

Configuration
-------------

[](#configuration)

Published config: `config/media-manager.php`

```
return [
    'disk' => null,
    'path' => 'files',
    'visibility' => 'public',
    'fallback_extension' => 'jpg',
    'naming_strategy' => 'uuid',

    'chunks' => [
        'directory' => 'chunks',
        'uploads_directory' => 'uploads',
    ],

    'routes' => [
        'enabled' => true,
        'prefix' => 'media-manager',
        'middleware' => [],
        'name' => 'media-manager.',
    ],
];
```

`disk => null` means the package uses `filesystems.default`.

The package registers `POST /media-manager/chunk-file` by default. Change `routes.prefix`, `routes.middleware`, or set `routes.enabled` to `false` if you need to avoid route conflicts.

Quick Start
-----------

[](#quick-start)

```
use HasanHawary\MediaManager\Facades\Media;

$path = Media::upload($request->file('avatar'), 'uploads/avatars');
$url = Media::url($path);
```

Fluent options:

```
$path = Media::on('public')
    ->visibility('private')
    ->fallbackExtension('png')
    ->generateName('uuid')
    ->upload($request->file('photo'), 'uploads/photos');
```

If no path is passed to `upload()`, the package uses `media-manager.path`.

Supported Sources
-----------------

[](#supported-sources)

SourceExampleUploaded file`$request->file('avatar')`Base64 data URI`data:image/png;base64,...`Plain base64 string`base64_encode($contents)`Remote URL`https://example.com/photo.jpg`Raw content`Hello world`Local path`storage_path('app/temp/logo.png')````
Media::upload($request->file('avatar'), 'avatars');
Media::upload($base64Image, 'images');
Media::fromUrl('https://example.com/photo.jpg', storedLocal: true)->to('images')->store();
Media::upload(file_get_contents('report.txt'), 'documents');
Media::upload(storage_path('app/temp/logo.png'), 'logos');
```

Remote URLs are validated before fetching. Local/private IP URLs are rejected by default to reduce SSRF risk.

Naming
------

[](#naming)

StrategyBehavior`uuid`Generated UUID filename`hash`MD5 hash for uploaded files, UUID fallback for generated content`timestamp`Timestamp plus random suffix`original`Keep the original filename when available`custom`Use `withName()` string or closure```
Media::generateName('hash')->upload($file, 'files');
Media::generateName('timestamp')->upload($file, 'files');
Media::keepOriginalName()->upload($file, 'files');
Media::withName(fn () => 'invoice_'.time().'.pdf')->upload($file, 'invoices');
```

Filenames are sanitized with `basename()` before storage.

Replacing Files
---------------

[](#replacing-files)

```
$path = Media::replace($user->avatar)
    ->upload($request->file('avatar'), 'uploads/avatars');

$user->update(['avatar' => $path]);
```

Input valueBehavior`null`, `''`, or `[]`Keep the old path`'delete'`Delete the old file and return `null`Same pathKeep the existing fileNew sourceStore the new file and delete the old file after successChunk Uploads
-------------

[](#chunk-uploads)

Use the fluent API directly:

```
$pathOrChunkNumber = Media::chunk([
    'file_name' => $request->input('file_name'),
    'chunk_number' => $request->integer('chunk_number'),
    'chunk_file' => $request->file('chunk_file'),
    'is_final' => $request->boolean('is_final'),
    'user_id' => $request->user()?->id,
    'directory' => 'videos',
]);
```

KeyRequiredDescription`file_name`yesFinal filename with extension`chunk_number`yes1-based chunk number`chunk_file`yes`Illuminate\Http\UploadedFile` chunk`is_final`noMerge chunks when true`user_id`sometimesUsed to isolate chunk directories`directory`noFinal merged file directoryIf `user_id` is not provided, Laravel apps fall back to `auth()->id()`. Outside Laravel auth, `user_id` is required.

Chunks are stored under `media-manager.chunks.directory`, merged in numeric order, streamed into the final file, and then cleaned up.

Or use the default package route:

```
POST /media-manager/chunk-file
```

Multipart form fields:

FieldRequiredDescription`file_name`yesFinal filename with extension`chunk_number`yes1-based chunk number`chunk_file`yesUploaded chunk file`is_final`noBoolean-ish value such as `1`, `true`, or `0``user_id`sometimesRequired when no authenticated Laravel user exists`directory`noFinal merged file directorySuccessful non-final response:

```
{
  "status": true,
  "code": 200,
  "message": "Chunk uploaded successfully.",
  "data": {
    "path": "1",
    "is_final": false
  }
}
```

Successful final response:

```
{
  "status": true,
  "code": 201,
  "message": "File assembled successfully.",
  "data": {
    "path": "videos/(1234)_movie.mp4",
    "is_final": true
  }
}
```

URLs
----

[](#urls)

```
Media::url($path);
Media::on('public')->url($path);
Media::on('s3')->temporaryUrl($path, 10);
Media::on('s3')->signedUrl($path, now()->addDay());
```

`url()`, `temporaryUrl()`, and `signedUrl()` return `null` for missing paths. Arrays of paths return an array when more than one path resolves.

Metadata
--------

[](#metadata)

```
$meta = Media::meta('uploads/docs/report.pdf');

$meta->path();
$meta->url();
$meta->size();
$meta->mime();
$meta->extension();
$meta->basename();
$meta->filename();
$meta->dirname();
$meta->lastModified();
$meta->hash();
$meta->dimensions();
$meta->toArray();
```

`MediaMeta` is JSON serializable.

File Operations
---------------

[](#file-operations)

```
Media::exists($path);
Media::delete($path);
Media::safeDelete($path);
```

`exists()`, `delete()`, and `safeDelete()` normalize package-generated disk URLs back to disk paths. External URLs are ignored.

`safeDelete()` moves files to `trash/` on the selected disk.

Exceptions
----------

[](#exceptions)

The package fails explicitly for invalid usage:

ExceptionExample`NoHandlerDefinedException`Calling `store()` before selecting a source`UnsupportedTypeException`Passing an unsupported source type`InvalidArgumentException`Invalid naming strategy, chunk data, empty disk name`ApiHandler` and `ZipHandler` are placeholders and throw `UnsupportedTypeException`.

Plain PHP Notes
---------------

[](#plain-php-notes)

These classes do not require a Laravel application container:

```
use HasanHawary\MediaManager\Support\FileNameGenerator;
use HasanHawary\MediaManager\Support\PathNormalizer;
use HasanHawary\MediaManager\Support\RemoteMediaFetcher;

$name = FileNameGenerator::generate('txt', 'uuid');
$path = (new PathNormalizer())->directory('../unsafe');
$isPublicUrl = (new RemoteMediaFetcher())->isValidUrl('https://example.com/file.jpg');
```

Storage-backed operations require Laravel filesystem components.

Testing
-------

[](#testing)

```
composer install
composer test
composer audit
```

The package test suite is isolated from any host project.

License
-------

[](#license)

MIT © [Hasan Hawary](https://github.com/hasanhawary)

###  Health Score

49

—

FairBetter than 94% of packages

Maintenance94

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 83.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~23 days

Recently: every ~49 days

Total

12

Last Release

28d ago

PHP version history (3 changes)v1.0.0PHP ^8.0

v1.0.2PHP &gt;8.0

1.5.0PHP &gt;=8.1 &lt;8.6

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/33836947?v=4)[Hassan Elhawary](/maintainers/hasanhawary)[@hasanhawary](https://github.com/hasanhawary)

---

Top Contributors

[![hasanhawary](https://avatars.githubusercontent.com/u/33836947?v=4)](https://github.com/hasanhawary "hasanhawary (5 commits)")[![hassanmuhammd](https://avatars.githubusercontent.com/u/126090873?v=4)](https://github.com/hassanmuhammd "hassanmuhammd (1 commits)")

---

Tags

filesystemlaravelfilesstoragemediaupload

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/hasanhawary-media-manager/health.svg)

```
[![Health](https://phpackages.com/badges/hasanhawary-media-manager/health.svg)](https://phpackages.com/packages/hasanhawary-media-manager)
```

###  Alternatives

[unisharp/laravel-filemanager

A file upload/editor intended for use with Laravel 5 to 10 and CKEditor / TinyMCE

2.2k3.5M85](/packages/unisharp-laravel-filemanager)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M131](/packages/roots-acorn)[api-platform/laravel

API Platform support for Laravel

58171.5k14](/packages/api-platform-laravel)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M194](/packages/laravel-ai)[mike-bronner/laravel-model-caching

Automatic caching for Eloquent models.

2.4k91.0k1](/packages/mike-bronner-laravel-model-caching)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
