FileNamingResolver - A lightweight library which helps to resolve a file/directory naming of uploaded files using various naming strategies

Overview

FileNamingResolver

A lightweight library which helps to resolve a file/directory naming of uploaded files using various naming strategies.

This library solves only naming things and do nothing with any files or directories directly. If you are looking for some filesystem abstraction layer - looks closer to Gaufrette, symfony/filesystem or Flysystem libraries.

Travis Status HHVM Status Scrutinizer Code Quality Code Coverage Software License Latest Version

SensioLabsInsight

Contents

Requirements

This library is standalone without any dependencies. To use it in your project ensure you correspond to the next requirements:

  • PHP 5.3 or higher

Installation

The preferred way to install this package is to use Composer:

$ composer require bocharsky-bw/file-naming-resolver

If you don't use Composer - register this package in your autoloader manually following PSR-4 autoloader standard or simply download this library and require the necessary files directly in your scripts:

require_once __DIR__ . '/path/to/library/src/FileNamingResolver.php';
// and other files you intend to use...

Usage

First of all, before using file naming resolver, you should determine which naming strategy to use. You can use different strategies out-of-the-box or easily create your own one by implementing the NamingStrategyInterface interface or extends the AbstractNamingStrategy class which already implemented it for you.

// don't forget to use namespaces
use FileNamingResolver\FileInfo;
use FileNamingResolver\FileNamingResolver;
use FileNamingResolver\NamingStrategy\HashNamingStrategy;

// First of all, upload new file or use any uploaded file on the your server

// Create source FileInfo object from FQFN of uploaded file
$srcFileInfo = new FileInfo(__DIR__.'/uploads/image.jpg');

// Create at least one naming strategy object
$hashStrategy = new HashNamingStrategy();

// Create file naming resolver and pass naming strategy to it
$namingResolver = new FileNamingResolver($hashStrategy);

// Resolve new name using specified naming strategy
$dstFileInfo = $namingResolver->resolve($srcFileInfo);
echo $dstFileInfo->toString(); // /var/www/html/web/uploads/4e/d3/a51a07c8e89ff8f228075b7fc76b.jpg

// Use rename() / move_uploaded_file() built-in functions, Gaufrette or any other filesystem
// abstraction library to move uploaded file to the directory according to suggested pathname.

NOTE: In all examples hereinafter the __DIR__ equals to /var/www/html/web.

FileInfo

The FileNamingResolver\FileInfo class extends \SplFileInfo object. For more info check the SplFileInfo. Below shown list of frequently used getters of this class:

$fileInfo = new FileInfo('/var/www/html/web/uploads/products/image.jpg');

echo $fileInfo->toString();     // '/var/www/html/web/uploads/products/image.jpg'
echo $fileInfo->getPathname();  // '/var/www/html/web/uploads/products/image.jpg'
echo $fileInfo->getPath();      // '/var/www/html/web/uploads/products'
echo $fileInfo->getFilename();  // 'image.jpg'
echo $fileInfo->getBasename();  // 'image'
echo $fileInfo->getExtension(); // 'jpg'
echo $fileInfo->getPathRelativeTo('/var/www/html/web');     // 'uploads/products'
echo $fileInfo->getPathnameRelativeTo('/var/www/html/web'); // 'uploads/products/image.jpg'

Strategy list

AggregateNamingStrategy

This naming strategy allows to use as many naming strategies as you need at once. Its aggregate results. Each new result pathname based on the previous one.

use FileNamingResolver\FileInfo;
use FileNamingResolver\FileNamingResolver;
use FileNamingResolver\NamingStrategy\AggregateNamingStrategy;
use FileNamingResolver\NamingStrategy\DatetimeNamingStrategy;
use FileNamingResolver\NamingStrategy\HashNamingStrategy;

$srcFileInfo = new FileInfo(__DIR__.'/uploads/image.jpg');

$datetimeStrategy = new DatetimeNamingStrategy();
$hashStrategy = new HashNamingStrategy();
// Create an aggregate naming strategy object
$strategies = [
    $datetimeStrategy,
    $hashStrategy,
    // and so on as many as you need...
];
$aggregateStrategy = new AggregateNamingStrategy($strategies);

$namingResolver = new FileNamingResolver($aggregateStrategy);
$dstFileInfo = $namingResolver->resolve($srcFileInfo);
echo $dstFileInfo->toString(); // /var/www/html/web/uploads/2015/12/9c/98/87cbf44f53c9f6fa08f44ce705c8.jpg

To reverse applying order of strategies pass true as second parameter to the constructor of AggregateNamingStrategy class:

$aggregateStrategy = new AggregateNamingStrategy($strategies, AggregateNamingStrategy::MODE_REVERSE);

$namingResolver = new FileNamingResolver($aggregateStrategy);
$dstFileInfo = $namingResolver->resolve($srcFileInfo);
echo $dstFileInfo->toString(); // /var/www/html/web/uploads/a0/cb/2015/12/11-23-35-039900.jpg

CallbackNamingStrategy

This naming strategy allows create a custom naming logic using custom callbacks.

use FileNamingResolver\FileInfo;
use FileNamingResolver\FileNamingResolver;
use FileNamingResolver\NamingStrategy\CallbackNamingStrategy;

$srcFileInfo = new FileInfo(__DIR__.'/uploads/image.jpg');

// Create a custom callback naming strategy object
$callbackStrategy = new CallbackNamingStrategy(function (FileInfo $srcFileInfo) {
    $dstFileInfo = $srcFileInfo
        // Add 'products' suffix to the path
        ->changePath($srcFileInfo->getPath().FileInfo::SEPARATOR_DIRECTORY.'products')
        // Generate custom basename of the file without extension
        ->changeBasename(time().'-'.uniqid()) // comment this line to keep original basename
        // or do whatever custom naming logic you want here...
    ;

    return $dstFileInfo;
});

$namingResolver = new FileNamingResolver($callbackStrategy);
$dstFileInfo = $namingResolver->resolve($srcFileInfo);
echo $dstFileInfo->toString(); // /var/www/html/web/uploads/products/1450004778-566d512a32d2c.jpg

ContentHashNamingStrategy

The naming behavior of hash naming strategy looks like Twig naming of cached files.

use FileNamingResolver\FileInfo;
use FileNamingResolver\FileNamingResolver;
use FileNamingResolver\NamingStrategy\ContentHashNamingStrategy;

$srcFileInfo = new FileInfo(__DIR__.'/uploads/image.jpg');

// Create a hash naming strategy object
$contentHashStrategy = new ContentHashNamingStrategy(
    // Hashing algorithm, by default: 'md5'
    ContentHashNamingStrategy::ALGORITHM_SHA1, // 'sha1'
    // Count of parts for explode, by default: 2
    3,
    // Length of each exploded part, by default: 2
    3,
    // Keep full filename for easy searching
    true
);

$namingResolver = new FileNamingResolver($contentHashStrategy);
$dstFileInfo = $namingResolver->resolve($srcFileInfo);
echo $dstFileInfo->toString(); // /var/www/html/web/uploads/4ed/3a5/1a0/4ed3a51a07c8e89ff8f228075b7fc76b.jpg

NOTE: Be sure that source file really exist before using ContentHashNamingStrategy otherwise an InvalidArgumentException will be thrown. You probably need to use a isFile() method on FileInfo object to be sure that file exists. It's necessary because this naming strategy try to hash a real file content.

DatetimeNamingStrategy

The naming behavior of datetime naming strategy looks like WordPress naming of uploaded media files.

use FileNamingResolver\FileInfo;
use FileNamingResolver\FileNamingResolver;
use FileNamingResolver\NamingStrategy\DatetimeNamingStrategy;

$srcFileInfo = new FileInfo(__DIR__.'/uploads/image.jpg');

// Create a datetime naming strategy object
$datetimeStrategy = new DatetimeNamingStrategy(
    // DateTime format for directories, by default: 'Y/m'
    DateTimeNamingStrategy::FORMAT_DIR_YEAR_MONTH_DAY,         // 'Y/m/d'
    // DateTime format for files, by default: 'H-i-s-u'
    DateTimeNamingStrategy::FORMAT_FILE_TIMESTAMP_MICROSECONDS // 'U-u'
);

$namingResolver = new FileNamingResolver($datetimeStrategy);
$dstFileInfo = $namingResolver->resolve($srcFileInfo);
echo $dstFileInfo->toString(); // /var/www/html/web/uploads/2015/12/13/1450004392-907500.jpg

HashNamingStrategy

The naming behavior of hash naming strategy looks like Twig naming of cached files.

use FileNamingResolver\FileInfo;
use FileNamingResolver\FileNamingResolver;
use FileNamingResolver\NamingStrategy\HashNamingStrategy;

$srcFileInfo = new FileInfo(__DIR__.'/uploads/image.jpg');

// Create a hash naming strategy object
$hashStrategy = new HashNamingStrategy(
    // Hashing algorithm, by default: 'md5'
    HashNamingStrategy::ALGORITHM_SHA1, // 'sha1'
    // Count of parts for explode, by default: 2
    3,
    // Length of each exploded part, by default: 2
    3,
    // Keep full filename for easy searching
    true
);

$namingResolver = new FileNamingResolver($hashStrategy);
$dstFileInfo = $namingResolver->resolve($srcFileInfo);
echo $dstFileInfo->toString(); // /var/www/html/web/uploads/4ed/3a5/1a0/4ed3a51a07c8e89ff8f228075b7fc76b.jpg

Example

There is a full working example how to upload files with a simple HTML form and built-in PHP functions using FileNamingResolver library.

%s" successfully uploaded to the "%s" web directory! :)', $dstFileInfo->getFilename(), $dstFileInfo->getPathRelativeTo(WEB_ROOT_DIR) // get path relative to the web directory ); } } ?>
">


require_once __DIR__.'/vendor/autoload.php';

use FileNamingResolver\FileInfo;
use FileNamingResolver\FileNamingResolver;
use FileNamingResolver\NamingStrategy\HashNamingStrategy;

// Define a few constants for convenience
define('WEB_ROOT_DIR', __DIR__);
define('UPLOAD_ROOT_DIR', WEB_ROOT_DIR.'/uploads');

// Check whether form was submitted...
if (isset($_POST['upload'])) {
    // and file was attached - process file uploading
    if ($_FILES['attachment']['tmp_name']) {
        $strategy = new HashNamingStrategy(); // or create any other strategy you need here
        $namingResolver = new FileNamingResolver($strategy); // use created naming strategy in resolver

        $dstFileInfo = new FileInfo(UPLOAD_ROOT_DIR.'/'.$_FILES['attachment']['name']); // build destination pathname
        $dstFileInfo = $namingResolver->resolve($dstFileInfo); // apply specified naming strategy to the destination file

        // Change extension based on mime type of uploaded file
        // WARNING: Could be skipped if you want to base on original extension in $_FILES['attachment']['name'] but it could cause some security issues!
        switch ($_FILES['attachment']['type']) {
            case 'image/jpeg':
                $extension = 'jpg';
                break;

            case 'image/png':
                $extension = 'png';
                break;

            default:
                $extension = 'bin';

        }
        // The FileInfo object is immutable so changeExtension() creates a new object.
        // Don't forget to override previous variable
        $dstFileInfo = $dstFileInfo->changeExtension($extension);

        // create non-existent directories for the destination file
        if (false === is_dir($dstFileInfo->getPath())) {
            if (false === mkdir($dstFileInfo->getPath(), 0777, true)) {
                throw new RuntimeException('Unable to create a directory for the destination file.');
            }
        }
        // move uploaded file according to the destination pathname
        if (false === move_uploaded_file($_FILES['attachment']['tmp_name'], $dstFileInfo->toString())) {
            throw new RuntimeException('Unable to move an uploaded file to the specified directory.');
        }

        // Do whatever you want after successful uploading (i.e redirect user after success uploading)
        echo sprintf(
            'File "%s" successfully uploaded to the "%s" web directory! :)',
            $dstFileInfo->getFilename(),
            $dstFileInfo->getPathRelativeTo(WEB_ROOT_DIR) // get path relative to the web directory
        );
    }
}

?>

<form action="" method="POST" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit" name="upload" value="Upload file">
form>

Contribution

Feel free to submit an Issue or create a Pull Request if you find a bug or just want to propose an improvement suggestion.

In order to propose a new feature, the best way is to submit an Issue and discuss it first.

Move UP

You might also like...
🌩支持多家云存储的云盘系统 (A project helps you build your own cloud in minutes)
🌩支持多家云存储的云盘系统 (A project helps you build your own cloud in minutes)

Cloudreve 支持多家云存储驱动的公有云文件系统. 演示站 • 讨论社区 • 文档 • 下载 • Telegram 群组 • 许可证 ✨ 特性 ☁️ 支持本机、从机、七牛、阿里云 OSS、腾讯云 COS、又拍云、OneDrive (包括世纪互联版) 作为存储端 📤 上传/下载 支持客户端直传

Detects file type by filename or content and generates correct mimetype.

FileTypeDetector Files type detector based on file name extension or file content (binary content). Usage Installation Supported formats Usage File Ty

kodbox is a file manager for web. It is a newly designed product based on kodexplorer.
kodbox is a file manager for web. It is a newly designed product based on kodexplorer.

kodbox is a file manager for web. It is a newly designed product based on kodexplorer. It is also a web code editor, which allows you to develop websites directly within the web browser.You can run kodbox either online or locally,on Linux, Windows or Mac based platforms

File manager module for the Lumen PHP framework.

Lumen File Manager File manager module for the Lumen PHP framework. Please note that this module is still under active development. NOTE: Branch 5.1 i

A web based file manager,web IDE / browser based code editor
A web based file manager,web IDE / browser based code editor

KodExplorer Update to kodbox: https://github.com/kalcaddle/kodbox Download | Demo It is recommended to use a new design upgrade product:kodbox 该项目处于维护

🛬🧾 A PHP8 TacView ACMI file format parser

A PHP8 TacView ACMI file format parser This package offers parsing support for TacView ACMI flight recordings version 2.1, it follows the standard des

Creating a file uploader with Laravel
Creating a file uploader with Laravel

File-Uploader File uploader is a simple group of restful APIs built in Laravel to upload file into a server and remove the file from that server. Tool

 Basic anonymous and registered upload storage for temporary share file self hosted.
Basic anonymous and registered upload storage for temporary share file self hosted.

TMPShareX Basic anonymous and registered upload storage for temporary share file self hosted. Server Requirement PHP 7.4.8 [Support PHP 8] Nginx 1.19.

Media gallery with CKEditor, TinyMCE and Summernote support. Built on Laravel file system.
Media gallery with CKEditor, TinyMCE and Summernote support. Built on Laravel file system.

Documents ・ Installation ・ Integration ・ Config ・ Customization ・ Events ・ Upgrade ・ Demo ・ FAQ Features File upload and management Uploading validati

Comments
  • Add feature to keep original file name

    Add feature to keep original file name

    Now we bite some letters off the beginning of a filename for ContentHashNamingStrategy, etc. i.e. d74a1cb2f57966565d735c6332b77474.jpg filename processing as /d7/4a/d74a1cb2f57966565d735c6332b77474.jpg instead of /d7/4a/1cb2f57966565d735c6332b77474.jpg. Actually, it helps searching files by its original filename.

    has PR 
    opened by bocharsky-bw 0
  • Scrutinizer Auto-Fixes

    Scrutinizer Auto-Fixes

    @bocharsky-bw requested this pull request.

    It consists of patches automatically generated for this project on Scrutinizer: https://scrutinizer-ci.com/g/bocharsky-bw/FileNamingResolver/

    opened by scrutinizer-auto-fixer 0
Owner
Victor Bocharsky
PHP developer, course writer, help scout, and expanding code blocks ninja at @SymfonyCasts (ex @KnpUniversity) - implement, merge, and deploy new features.
Victor Bocharsky
Uguu is a simple lightweight temporary file host with support for drop, paste, click and API uploading.

Uguu What is Uguu? Uguu is a simple lightweight temporary file hosting and sharing platform, but can also be used as a permanent file host. Features O

Eric Johansson (neku) 547 Dec 28, 2022
A lightweight file manager with full ShareX, Screencloud support and more

XBackBone is a simple, self-hosted, lightweight PHP file manager that support the instant sharing tool ShareX and *NIX systems. It supports uploading

Sergio Brighenti 751 Jan 8, 2023
Pomf is a simple lightweight file host with support for drop, paste, click and API uploading.

Pomf Pomf is a simple file uploading and sharing platform. Features One click uploading, no registration required A minimal, modern web interface Drag

Pomf 772 Jan 8, 2023
FIle Uploader is a php package to aid fast , easy and safe file upload

FILE UPLOADER FIle Uploader is a php package to aid fast , easy and safe file upload installation composer require codad5/file-helper Features Fast an

Aniezeofor Chibueze Michael 2 Sep 3, 2022
This package used to upload files using laravel-media-library before saving model.

Laravel Media Uploader This package used to upload files using laravel-media-library before saving model. In this package all uploaded media will be p

Ahmed Fathy 312 Dec 12, 2022
Watch changes in the file system using PHP

Watch changes in the file system using PHP This package allows you to react to all kinds of changes in the file system. Here's how you can run code wh

Spatie 170 Dec 25, 2022
Upload File Library For PHP ( Simple & Easy User )

Upload File Library For Backend/ServerSide PHP ( Simple & Easy For Use ), Support Multiple Upload

Lamhot Simamora 1 Oct 12, 2021
Gotipath Storage is a file storage library for PHP. It provides one interface to interact with FTP/SFTP.

Gotipath Storage is a file storage library for PHP. It provides one interface to interact with FTP/SFTP. When you use this package, you're protected from vendor lock-in, That mean you can connect to any FTP/SFTP storage. Also it's comes with base URL option to connect Gotipath CDN.

Gotipath 2 Nov 3, 2021
PHPProject is a library written in pure PHP that provides a set of classes to write to different project management file formats

PHPProject PHPProject is a library written in pure PHP that provides a set of classes to write to different project management file formats, i.e. Micr

PHPOffice 192 Dec 17, 2022
PHP library that provides a filesystem abstraction layer − will be a feast for your files!

Gaufrette Gaufrette provides a filesystem abstraction layer. Why use Gaufrette? Imagine you have to manage a lot of medias in a PHP project. Lets see

KNP Labs 2.4k Jan 7, 2023