bocharsky-bw/file-naming-resolver

一个轻量级的库,用于通过各种命名策略解决上传文件的文件/目录命名。

v0.3.2 2016-11-15 21:42 UTC

This package is auto-updated.

Last update: 2024-08-29 03:26:16 UTC


README

一个轻量级的库,用于通过各种命名策略解决上传文件的文件/目录命名。

此库仅解决命名问题,不会直接处理任何文件或目录。如果您正在寻找一些文件系统抽象层,则更接近于 Gaufrettesymfony/filesystemFlysystem 库。

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

SensioLabsInsight

内容

需求

此库是独立的,没有依赖。要在项目中使用它,请确保符合以下要求

  • PHP 5.3 或更高版本

安装

安装此包的首选方法是使用 Composer

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

如果您不使用 Composer - 请根据 PSR-4 自动加载标准手动注册此包,或者简单地下载此库并在脚本中直接 require 必要的文件

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

使用

首先,在使用文件命名解析器之前,您应该确定要使用哪种命名策略。您可以使用不同的策略,也可以通过实现 NamingStrategyInterface 接口或扩展已为您实现它的 AbstractNamingStrategy 类来轻松创建自己的策略。

// 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.

注意:以下所有示例中 __DIR__ 等于 /var/www/html/web

文件信息

FileNamingResolver\FileInfo 类扩展了 \SplFileInfo 对象。有关更多信息,请查看 SplFileInfo。以下列出了此类常用的获取器

$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'

策略列表

聚合命名策略

此命名策略允许同时使用任意数量的命名策略。它会聚合结果。每个新结果路径基于上一个路径。

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

要将策略的适用顺序反转,请将 true 作为 AggregateNamingStrategy 类构造函数的第二个参数传递

$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

回调命名策略

此命名策略允许使用自定义回调创建自定义命名逻辑。

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

内容哈希命名策略

哈希命名策略的命名行为类似于 Twig 缓存文件的命名。

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

注意:在使用 ContentHashNamingStrategy 之前,请确保源文件确实存在,否则将抛出 InvalidArgumentException。您可能需要使用 FileInfo 对象上的 isFile() 方法来确保文件存在。这是必要的,因为此命名策略尝试对实际的文件内容进行哈希处理。

日期时间命名策略

日期时间命名策略的命名行为类似于 WordPress 上传媒体文件的命名。

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

哈希命名策略

哈希命名策略的命名行为类似于 Twig 缓存文件的命名。

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

示例

以下是一个完整的工作示例,演示如何使用 FileNamingResolver 库和简单的 HTML 表单以及内置的 PHP 函数上传文件。

<?php

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 "<b>%s</b>" successfully uploaded to the "<b>%s</b>" 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>

贡献

如果您发现任何错误或希望提出改进建议,请随时提交一个问题或创建一个拉取请求

为了提出一个新功能,最佳的方式是首先提交一个问题并对其进行讨论。

向上移动