https://github.com/itstructure/laravel-media-file-uploader
Uploader of different files
https://github.com/itstructure/laravel-media-file-uploader
audio file image laravel office pdf upload uploader video
Last synced: 4 months ago
JSON representation
Uploader of different files
- Host: GitHub
- URL: https://github.com/itstructure/laravel-media-file-uploader
- Owner: itstructure
- License: mit
- Created: 2024-01-02T07:03:34.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2025-02-27T17:16:49.000Z (over 1 year ago)
- Last Synced: 2025-05-09T01:47:14.672Z (about 1 year ago)
- Topics: audio, file, image, laravel, office, pdf, upload, uploader, video
- Language: PHP
- Homepage:
- Size: 2.33 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: changelog.md
- License: LICENSE
Awesome Lists containing this project
README
# Laravel Media File Uploader - MFU
[](https://packagist.org/packages/itstructure/laravel-media-file-uploader)
[](https://packagist.org/packages/itstructure/laravel-media-file-uploader)
[](https://packagist.org/packages/itstructure/laravel-media-file-uploader)
[](https://packagist.org/packages/itstructure/laravel-media-file-uploader)
[](https://scrutinizer-ci.com/g/itstructure/laravel-media-file-uploader/build-status/main)
[](https://scrutinizer-ci.com/g/itstructure/laravel-media-file-uploader/?branch=main)
## 1 Introduction
This package is to upload different media files to Local or remote Amazon S3 storage.

## 2 Requirements
- laravel 6+ | 7+ | 8+ | 9+ | 10+ | 11+ | 12+
- Bootstrap 4 for styling
- JQuery
- php >= 7.2.5
- composer 2
- One of the next php extensions: GD|Imagick|Gmagick
## 3 Installation
### 3.1 Install package
#### General from remote Packagist repository
Run the composer command:
`composer require itstructure/laravel-media-file-uploader "^1.0.6"`
#### If you are testing this package from a local server directory
In application `composer.json` file set the repository, as in example:
```json
"repositories": [
{
"type": "path",
"url": "../laravel-media-file-uploader",
"options": {
"symlink": true
}
}
],
```
Here,
**../laravel-media-file-uploader** - directory path, which has the same directory level as application and contains MFU package.
Then run command:
`composer require itstructure/laravel-media-file-uploader:dev-main --prefer-source`
### 3.3 Publish files - Required part
- To publish config run command:
`php artisan uploader:publish --only=config`
It stores config file to `config` folder.
Else you can use `--force` argument to rewrite already published file.
- To publish migrations run command:
`php artisan uploader:publish --only=migrations`
It stores migration files to `database/migrations` folder.
Else you can use `--force` argument to rewrite already published files.
- To publish assets (js and css) run command:
`php artisan uploader:publish --only=assets`
It stores js and css files to `public/vendor/uploader` folder.
Else you can use `--force` argument to rewrite already published files.
### 3.4 Publish files - Custom part
- To publish views run command:
`php artisan uploader:publish --only=views`
It stores view files to `resources/views/vendor/uploader` folder.
Else you can use `--force` argument to rewrite already published file.
- To publish translations run command:
`php artisan uploader:publish --only=lang`
It stores translation files to `resources/lang/vendor/uploader` folder.
Else you can use `--force` argument to rewrite already published file.
### 3.5 Publish files - All parts if needed
- To publish all parts run command without `only` argument:
`php artisan uploader:publish`
Else you can use `--force` argument to rewrite already published files.
### 3.6 Run migrations
- Run command:
`php artisan migrate`
## 4 Configure
### 4.1 Set default filesystem disk
In a config file `filesystems.php` set the next custom settings (set default disk which you wish) and create needed base upload folder:
```php
'default' => env('FILESYSTEM_DISK', 'local'),
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/uploads'),
'throw' => false,
'url' => env('APP_URL') . '/storage/',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
'visibility' => 'public',
],
],
'links' => [
public_path('storage') => storage_path('app/uploads'),
],
```
Run command to create symbolic links:
`php artisan storage:link`
### 4.2 Set assets
**Pay Attention! This option is needed just in the next cases:**
- If you use a **File setter** in your app html forms (see **5.3 Digging deeper** / **5.3.3 Use FileSetter** point).
- If you use an **Album editor** (see in **5.1 Routes part**).
**Make sure** you use a **Bootstrap 4** for styling and **JQuery** in your application.
#### 4.2.1 Custom body layout case
So, set the next css assets between `head` tags of your app layout:
```html
```
Set the next js asset at the end of the `body` tag of your app layout:
```html
```
Note: `vendor/uploader/js/jquery.min.js` is required just if **JQuery** is absent in your application.
#### 4.2.2 If you use [AdminLTE](https://github.com/jeroennoten/Laravel-AdminLTE) package in your project
```php
'plugins' => [
'Uploader' => [
'active' => true,
'files' => [
[
'type' => 'css',
'asset' => true,
'location' => '/vendor/uploader/css/modal.css',
],
[
'type' => 'css',
'asset' => true,
'location' => '/vendor/uploader/css/file-area.css',
],
[
'type' => 'js',
'asset' => true,
'location' => '/vendor/uploader/js/file-setter.js',
],
],
],
]
```
Pay attention: Not recommended using of `asset()` in AdminLTE config file, because it may cause an error with **UrlGenerator.php** when you will run fore example `composer install` later.
### 4.3 Change `uploader.php` config file.
This file is **intuitive**.
But at this stage, pay attention to the next important options:
- Routing middlewares. By default it is empty array, you can set for example like this:
```php
'routing' => [
'middlewares' => ['auth'],
],
```
This middlewares will be applied in the `routes/uploader.php`.
- Albums layout (**Needed if you use Album editor**). By default it is empty string, you can set for example like this:
```php
'albums' => [
'layout' => 'adminlte::page', // In case if you use AdminLTE. Or you can set your special layout.
],
```
## 5 Usage
### 5.1 Routes part
There are already integrated base MFU routes to manage **files** and **albums**. See in `routes/uploader.php` package file.
The next routes are available by default:
- **Uploading section**
For GET request method
- `http://example-domain.com/uploader/file/download/{id}` (Name: **uploader_file_download**)
For POST request method
- `http://example-domain.com/uploader/file/upload` (Name: **uploader_file_upload**)
- Required request field is **file**.
- Optional/required request meta data fields: **[data]alt**, **[data]title**, **[data]description**, **[data]owner_id**, **[data]owner_name**, **[data]owner_attribute**, **[data]needed_file_type**, **[data]sub_dir**.
- `http://example-domain.com/uploader/file/update` (Name: **uploader_file_update**)
- Required request field is **id**.
- Optional request field is **file**.
- Optional/required request meta data fields: **[data]alt**, **[data]title**, **[data]description**, **[data]needed_file_type**, **[data]sub_dir**.
- `http://example-domain.com/uploader/file/delete` (Name: **uploader_file_delete**)
- Required request field is **id**.
- `http://example-domain.com/uploader/file/preview` (Name: **uploader_file_preview**)
- Required request field is **id**.
- Optional request field is **location**. See more for **preview** option in config `uploader.php` (there are some html attributes for concrete file types and their previews). If not set, returned preview will be with html attributes according with `Previewer::LOCATION_FILE_INFO`.
Also if it is an image, `Previewer` will return an image with sizes, according with **thumbAlias** option in config. If **thumbAlias** is not set or there is no such location, `Previewer` will return image with sizes according with `SaveProcessor::THUMB_ALIAS_SMALL`.
Notes:
- If uploading file is an **image**, then additional thumbnails will be created according with their settings in **thumbSizes** config option.
- Requirement/optionality for request meta data fields is set in **metaDataValidationRules** option of config `uploader.php` file.
- If **checkExtensionByFileType** option is **true**, then **[data]needed_file_type** is required automatically.
- **Managing section**
For GET request method
- `http://example-domain.com/uploader/managers/file-list` (Name: **uploader_file_list_manager**)
- `http://example-domain.com/uploader/managers/file-upload` (Name: **uploader_file_upload_manager**)
- `http://example-domain.com/uploader/managers/file-edit/{id}` (Name: **uploader_file_edit_manager**)
For POST request method
- `http://example-domain.com/uploader/managers/file-list/delete` (Name: **uploader_file_list_delete**)
- Required request field is **items** - it is an array of file's ID's.
- **Album editor section**
- Image albums
For GET request method
- `http://example-domain.com/uploader/albums/image/list` (Name: **uploader_image_album_list**)
- `http://example-domain.com/uploader/albums/image/create` (Name: **uploader_image_album_create**)
- `http://example-domain.com/uploader/albums/image/edit/{id}` (Name: **uploader_image_album_edit**)
- `http://example-domain.com/uploader/albums/image/view/{id}` (Name: **uploader_image_album_view**)
For POST request method
- `http://example-domain.com/uploader/albums/image/store` (Name: **uploader_image_album_store**)
- `http://example-domain.com/uploader/albums/image/update/{id}` (Name: **uploader_image_album_update**)
- `http://example-domain.com/uploader/albums/image/delete` (Name: **uploader_image_album_delete**)
- Audio albums
For GET request method
- `http://example-domain.com/uploader/albums/audio/list` (Name: **uploader_audio_album_list**)
- `http://example-domain.com/uploader/albums/audio/create` (Name: **uploader_audio_album_create**)
- `http://example-domain.com/uploader/albums/audio/edit/{id}` (Name: **uploader_audio_album_edit**)
- `http://example-domain.com/uploader/albums/audio/view/{id}` (Name: **uploader_audio_album_view**)
For POST request method
- `http://example-domain.com/uploader/albums/audio/store` (Name: **uploader_audio_album_store**)
- `http://example-domain.com/uploader/albums/audio/update/{id}` (Name: **uploader_audio_album_update**)
- `http://example-domain.com/uploader/albums/audio/delete` (Name: **uploader_audio_album_delete**)
- Video albums
For GET request method
- `http://example-domain.com/uploader/albums/video/list` (Name: **uploader_video_album_list**)
- `http://example-domain.com/uploader/albums/video/create` (Name: **uploader_video_album_create**)
- `http://example-domain.com/uploader/albums/video/edit/{id}` (Name: **uploader_video_album_edit**)
- `http://example-domain.com/uploader/albums/video/view/{id}` (Name: **uploader_video_album_view**)
For POST request method
- `http://example-domain.com/uploader/albums/video/store` (Name: **uploader_video_album_store**)
- `http://example-domain.com/uploader/albums/video/update/{id}` (Name: **uploader_video_album_update**)
- `http://example-domain.com/uploader/albums/video/delete` (Name: **uploader_video_album_delete**)
- Application albums
For GET request method
- `http://example-domain.com/uploader/albums/application/list` (Name: **uploader_application_album_list**)
- `http://example-domain.com/uploader/albums/application/create` (Name: **uploader_application_album_create**)
- `http://example-domain.com/uploader/albums/application/edit/{id}` (Name: **uploader_application_album_edit**)
- `http://example-domain.com/uploader/albums/application/view/{id}` (Name: **uploader_application_album_view**)
For POST request method
- `http://example-domain.com/uploader/albums/application/store` (Name: **uploader_application_album_store**)
- `http://example-domain.com/uploader/albums/application/update/{id}` (Name: **uploader_application_album_update**)
- `http://example-domain.com/uploader/albums/application/delete` (Name: **uploader_application_album_delete**)
- Word albums
For GET request method
- `http://example-domain.com/uploader/albums/word/list` (Name: **uploader_word_album_list**)
- `http://example-domain.com/uploader/albums/word/create` (Name: **uploader_word_album_create**)
- `http://example-domain.com/uploader/albums/word/edit/{id}` (Name: **uploader_word_album_edit**)
- `http://example-domain.com/uploader/albums/word/view/{id}` (Name: **uploader_word_album_view**)
For POST request method
- `http://example-domain.com/uploader/albums/word/store` (Name: **uploader_word_album_store**)
- `http://example-domain.com/uploader/albums/word/update/{id}` (Name: **uploader_word_album_update**)
- `http://example-domain.com/uploader/albums/word/delete` (Name: **uploader_word_album_delete**)
.........................................................
................Next albums...............
.........................................................
**E.t.c...** See in `routes/uploader.php` package file the next albums routes for **Excel**, **Visio**, **PowerPoint**, **PDF**, **Text**, **Other** albums. They have similar principle.
**Album editor** POST request method fields are equal for all albums:
- Required request fields for store: **title**, **description**.
- Required request fields for update: **title**, **description**. Field **id** is in route url.
- Required request field for delete: **items** - it is an array of album's ID's.
### 5.2 Easy quick way
#### 5.2.1 Access to File list manager
- Go directly to **uploader_file_list_manager** route: `http://example-domain.com/uploader/managers/file-list`
- Go to File list using **iframe**:
```blade
```

#### 5.2.2 Access to File upload manager
If to click on green **Uploader** button in a file list manager, you will go to **uploader_file_upload_manager** route: `http://example-domain.com/uploader/managers/file-upload`.

#### 5.2.3 Access to File edit manager
If to click on green edition button in a file list manager, you will go to **uploader_file_edit_manager** route: `http://example-domain.com/uploader/managers/file-edit/{id}`:
```php
route('uploader_file_edit_manager', ['id' => 1])
```

#### 5.2.4 Access to Media file preview
If you have got a media file entry `$mediaFile` by `Itstructure\MFU\Models\Mediafile` model entity:
Here you can use some of the next options:
`\Itstructure\MFU\Services\Previewer::LOCATION_FILE_ITEM`
`\Itstructure\MFU\Services\Previewer::LOCATION_FILE_INFO`
`\Itstructure\MFU\Services\Previewer::LOCATION_EXISTING`
#### 5.2.5 Download Media file
Use route:
```php
route('uploader_file_download', ['id' => 1])
```
#### 5.2.6 Access to Album Editor
Simply use albums routes, described above in **Album editor section** of **5.1 Routes part**.
But pay attention! You must set a layout for album editor:
```php
'albums' => [
'layout' => 'adminlte::page',
],
```
Value `adminlte::page` is for case if you use [AdminLTE](https://github.com/jeroennoten/Laravel-AdminLTE). Or you can set your special layout.
Image album list example looks like this:

Image album edition page example looks like this:

### 5.3 Digging deeper
#### 5.3.1 Data base structure

#### 5.3.2 Short architecture structure and request way for uploading process in simple words
1. Call `UploadController` method.
2. Call static method from `Itstructure\MFU\Facades\Uploader` facade in controller method.
3. Get instance of Uploader service `Itstructure\MFU\Services\Uploader::getInstance($config)` and call here a facade's method.
4. Get instance of needed processor, with set config data from service to this:
`Itstructure\MFU\Processors\UploadProcessor` or
`Itstructure\MFU\Processors\UpdateProcessor` or
`Itstructure\MFU\Processors\DeleteProcessor`.
5. Set process parameters and then call it's `run()` method.
See inside core.
#### 5.3.3 Use FileSetter
FileSetter is needed to set **file id** in to the form field and file **preview** to special container before sending request to controller during saving some entity: Page, Catalog, Product e.t.c.
Example FileSetter using for **thumbnail**:
```blade
@php
$thumbModel = isset($model) ? $model->getThumbnailModel() : null;
@endphp
@if(!empty($thumbModel))
{!! \Itstructure\MFU\Facades\Previewer::getPreviewHtml($thumbModel, \Itstructure\MFU\Services\Previewer::LOCATION_FILE_INFO) !!}
@endif
@if(!empty($thumbModel))
{{ $thumbModel->title }}
@endif
@if(!empty($thumbModel))
{{ $thumbModel->description }}
@endif
@php
$fileSetterConfig = [
'attribute' => Itstructure\MFU\Processors\SaveProcessor::FILE_TYPE_THUMB,
'value' => !empty($thumbModel) ? $thumbModel->id : null,
'openButtonName' => trans('uploader::main.set_thumbnail'),
'clearButtonName' => trans('uploader::main.clear'),
'mediafileContainerId' => isset($model) ? 'thumbnail_container_' . $model->id : 'thumbnail_container',
'titleContainerId' => isset($model) ? 'thumbnail_title_' . $model->id : 'thumbnail_title',
'descriptionContainerId' => isset($model) ? 'thumbnail_description_' . $model->id : 'thumbnail_description',
//'callbackBeforeInsert' => 'function (e, v) {console.log(e, v);}',//Custom
'neededFileType' => Itstructure\MFU\Processors\SaveProcessor::FILE_TYPE_THUMB,
'subDir' => isset($model) ? $model->getTable() : null
];
$ownerConfig = isset($ownerParams) && is_array($ownerParams) ? array_merge([
'ownerAttribute' => Itstructure\MFU\Processors\SaveProcessor::FILE_TYPE_THUMB
], $ownerParams) : [];
$fileSetterConfig = array_merge($fileSetterConfig, $ownerConfig);
@endphp
@fileSetter($fileSetterConfig)
```
Visually it looks like that:

If to click on **Set thumbnail** button, then file list manager will be opened, but with additional button "V":

This button is to choose a concrete file and insert it's preview in to the `thumbnail_container` and it's ID in to the automatically rendered form field by `attribute` option.
See next point **5.3.4** to understand how this selected file can be linked with a parent owner, like for example: Page, Product e.t.c...
#### 5.3.4 Link media files with parent owner
For example you use `Product` eloquent model, which contains **albums** and **media files** both.
Albums and media files can be linked with Product, after Product is saved, through `owners_albums` and `owners_mediafiles` DB relations.
This relations are set by `BehaviorMediafile` and `BehaviorAlbum` classes automatically.
```php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Itstructure\MFU\Interfaces\BeingOwnerInterface;
use Itstructure\MFU\Behaviors\Owner\{BehaviorMediafile, BehaviorAlbum};
use Itstructure\MFU\Processors\SaveProcessor;
use Itstructure\MFU\Models\Albums\AlbumTyped;
use Itstructure\MFU\Traits\{OwnerBehavior, Thumbnailable};
class Product extends Model implements BeingOwnerInterface
{
use Thumbnailable, OwnerBehavior;
protected $table = 'products';
protected $fillable = ['title', 'alias', 'description', 'price', 'category_id'];
public function getItsName(): string
{
return $this->getTable();
}
public function getPrimaryKey()
{
return $this->getKey();
}
public static function getBehaviorMadiafileAttributes(): array
{
return [SaveProcessor::FILE_TYPE_THUMB, SaveProcessor::FILE_TYPE_IMAGE];
}
public static function getBehaviorAlbumAttributes(): array
{
return [AlbumTyped::ALBUM_TYPE_IMAGE];
}
public static function getBehaviorAttributes(): array
{
return array_merge(static::getBehaviorMadiafileAttributes(), static::getBehaviorAlbumAttributes());
}
protected static function booted(): void
{
$behaviorMediafile = BehaviorMediafile::getInstance(static::getBehaviorMadiafileAttributes());
$behaviorAlbum = BehaviorAlbum::getInstance(static::getBehaviorAlbumAttributes());
static::saved(function (Model $ownerModel) use ($behaviorMediafile, $behaviorAlbum) {
if ($ownerModel->wasRecentlyCreated) {
$behaviorMediafile->link($ownerModel);
$behaviorAlbum->link($ownerModel);
} else {
$behaviorMediafile->refresh($ownerModel);
$behaviorAlbum->refresh($ownerModel);
}
});
static::deleted(function (Model $ownerModel) use ($behaviorMediafile, $behaviorAlbum) {
$behaviorMediafile->clear($ownerModel);
$behaviorAlbum->clear($ownerModel);
});
}
}
```
The main rules:
- It is very important to be implemented from `BeingOwnerInterface`!
- It is very important to use `OwnerBehavior` trait. Some required BASE methods by `BeingOwnerInterface` are already existing in this trait.
- It is very important to make the next methods: `getItsName()`, `getPrimaryKey()`.
- It is very important to add method `booted()` with behaviour instances.
- It is very important to set `getBehaviorAttributes()` with attributes list, which are used in a blade form for **FileSetter**!
See deeper in to core and imagine how it works :-)
Go next...
It is very important to use MFU blade partials correctly in your application blade forms!
Short cut example for the blade form with using
`uploader::partials.thumbnail`,
`uploader::partials.new-mediafiles`,
`uploader::partials.existing-mediafiles`,
`uploader::partials.albums-form-list`:
```blade
@include('uploader::partials.thumbnail', ['model' => $model ?? null, 'ownerParams' => $ownerParams ?? null])
Title
@if ($errors->has('title'))
{{ $errors->first('title') }}
@endif
..........
..........
{{ trans('uploader::main.new_files') }}
@include('uploader::partials.new-mediafiles', [
'fileType' => \Itstructure\MFU\Processors\SaveProcessor::FILE_TYPE_IMAGE,
'ownerParams' => $ownerParams ?? null
])
@if(!empty($edition))
{{ trans('uploader::main.existing_files') }}
@include('uploader::partials.existing-mediafiles', [
'edition' => true,
'fileType' => \Itstructure\MFU\Processors\SaveProcessor::FILE_TYPE_IMAGE,
'ownerParams' => $ownerParams ?? null,
'mediaFiles' => $mediaFiles ?? []
])
@endif
@if(!empty($allImageAlbums) && !$allImageAlbums->isEmpty())
{{ trans('uploader::main.image_albums') }}
@include('uploader::partials.albums-form-list', [
'albums' => $allImageAlbums,
'edition' => true
])
@endif
Create
```
To clarify:
By `fileType` there will be set a field `image[]`, which will be set by `fill()` method in `Itstructure\MFU\Traits\OwnerBehavior` trait using `getBehaviorAttributes()`,
and then it's value will be put in to the `BehaviorMediafile` object during `booted()` calling after for example `Product` is saved. Then a table `owners_mediafiles` will be filled.
Link between `Product` and `Mediafile` will be created.
Product edition page example looks like this:

To see more, how that example works in global, see real example here: [Laravel Microshop](https://github.com/itstructure/laravel-microshop).
I hope you will be happy with this package. Good luck with your development!
With all respect, Andrey!
## License
Copyright © 2024-2025 Andrey Girnik girnikandrey@gmail.com.
Licensed under the [MIT license](http://opensource.org/licenses/MIT). See LICENSE.txt for details.