tourze/file-storage-bundle 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

tourze/file-storage-bundle

Composer 安装命令:

composer require tourze/file-storage-bundle

包简介

Symfony bundle for file storage management with upload, validation, and cleanup features

README 文档

README

English | 中文

PHP Version License

Build Status

Code Coverage

Symfony Bundle for file upload and storage management with Flysystem integration.

Table of Contents

Features

  • Flysystem integration for flexible file storage (local, S3, FTP, etc.)
  • Separate upload endpoints for anonymous and authenticated users
  • Database-driven file type management with configurable permissions
  • File metadata storage in database with user tracking
  • Automatic file hash calculation (MD5, SHA1)
  • File organization by year/month structure
  • Soft delete support
  • Automatic cleanup of anonymous files
  • File statistics
  • Duplicate detection by hash
  • EasyAdmin integration ready

Installation

composer require tourze/file-storage-bundle

Configuration

Add the bundle to your config/bundles.php:

return [
    // ...
    Tourze\FileStorageBundle\FileStorageBundle::class => ['all' => true],
];

The bundle automatically configures Flysystem with a local adapter. No additional configuration is needed for basic usage.

Database Setup

Run migrations to create the required tables:

bin/console doctrine:migrations:diff
bin/console doctrine:migrations:migrate

Load default file types:

bin/console doctrine:fixtures:load --append --group=file-types

Usage

Anonymous Upload

POST /api/files/upload/anonymous
Content-Type: multipart/form-data

file: <file>

Response:

{
  "success": true,
  "file": {
    "id": 1,
    "originalName": "document.pdf",
    "fileName": "document-65abc123.pdf",
    "mimeType": "application/pdf",
    "fileSize": 1048576,
    "md5Hash": "098f6bcd4621d373cade4e832627b4f6",
    "createdAt": "2024-01-10 10:30:00"
  }
}

Note: Anonymous files are automatically deleted after 1 hour.

Member Upload

POST /api/files/upload/member
Authorization: Bearer <token>
Content-Type: multipart/form-data

file: <file>

Response:

{
  "success": true,
  "file": {
    "id": 2,
    "originalName": "report.xlsx",
    "fileName": "report-65abc456.xlsx",
    "mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "fileSize": 2097152,
    "md5Hash": "5d41402abc4b2a76b9719d911017c592",
    "createdAt": "2024-01-10 11:00:00",
    "userId": 123
  }
}

Get Allowed File Types

# For anonymous users
GET /api/files/allowed-types/anonymous

# For members
GET /api/files/allowed-types/member

Response:

{
  "allowedTypes": [
    {
      "name": "JPEG Image",
      "mimeType": "image/jpeg",
      "extension": "jpg",
      "maxSize": 10485760
    },
    {
      "name": "PDF Document",
      "mimeType": "application/pdf",
      "extension": "pdf",
      "maxSize": 20971520
    }
  ]
}

Get File Info

GET /api/files/{id}

File Type Management

File types are stored in the database and can be managed via EasyAdmin or programmatically:

// Create a new file type
$fileType = new FileType();
$fileType->setName('PowerPoint Presentation')
    ->setMimeType('application/vnd.ms-powerpoint')
    ->setExtension('ppt')
    ->setMaxSize(30 * 1024 * 1024) // 30MB
    ->setUploadType('member') // 'anonymous', 'member', or 'both'
    ->setIsActive(true);

$entityManager->persist($fileType);
$entityManager->flush();

Console Commands

Clean Anonymous Files

Remove anonymous files older than specified hours:

# Delete anonymous files older than 1 hour (default)
bin/console file-storage:clean-anonymous

# Delete anonymous files older than 3 hours
bin/console file-storage:clean-anonymous --hours=3

# Dry run - show what would be deleted without actually deleting
bin/console file-storage:clean-anonymous --dry-run

# Verbose output showing file details
bin/console file-storage:clean-anonymous --dry-run -v

Delete Files

Delete all files in a specified directory recursively:

# Delete all files in a directory (requires confirmation)
bin/console file-storage:delete path/to/directory

# Skip confirmation prompt
bin/console file-storage:delete path/to/directory --force

# Also delete empty directories
bin/console file-storage:delete path/to/directory --include-dirs

# Dry run - show what would be deleted without actually deleting
bin/console file-storage:delete path/to/directory --dry-run

# Verbose output showing file details
bin/console file-storage:delete path/to/directory --dry-run -v

# Combined: delete files and directories with force
bin/console file-storage:delete path/to/directory -f -d

Cron Job Example

Add to your crontab to run every hour:

0 * * * * cd /path/to/project && bin/console file-storage:clean-anonymous

File Statistics

Display file storage statistics:

# Show file statistics
bin/console file-storage:stats

# Output example:
# File Storage Statistics
# =======================
# Total files: 1,234
# Total size: 5.67 GB
# Average file size: 4.71 MB
# Anonymous files: 456
# Member files: 778

Advanced Storage Configuration

The bundle uses Flysystem for file storage abstraction. By default, it uses a local filesystem adapter.

Custom Storage Adapter

To use a different storage backend (e.g., AWS S3, FTP, etc.), create your own factory:

// src/Factory/S3FilesystemFactory.php
namespace App\Factory;

use Aws\S3\S3Client;
use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemOperator;

class S3FilesystemFactory
{
    public function __construct(
        private readonly S3Client $s3Client,
        private readonly string $bucket,
    ) {
    }

    public function createFilesystem(): FilesystemOperator
    {
        $adapter = new AwsS3V3Adapter($this->s3Client, $this->bucket);
        return new Filesystem($adapter);
    }
}

Entity Structure

File Entity

  • originalName - Original uploaded filename
  • fileName - Generated unique filename
  • filePath - Relative path to file
  • mimeType - File MIME type
  • fileSize - File size in bytes
  • md5Hash - MD5 hash of file content
  • sha1Hash - SHA1 hash of file content
  • createTime - Upload timestamp
  • updateTime - Last update timestamp
  • metadata - JSON field for additional data
  • storageType - Storage backend type (default: local)
  • isActive - Soft delete flag
  • userId - User ID for member uploads (null for anonymous)

FileType Entity

  • name - Display name (e.g., "JPEG Image")
  • mimeType - MIME type (e.g., "image/jpeg")
  • extension - File extension (e.g., "jpg")
  • maxSize - Maximum file size in bytes
  • uploadType - Who can upload ('anonymous', 'member', 'both')
  • isActive - Whether this type is enabled
  • createTime - Creation timestamp
  • updateTime - Last update timestamp

Security

Access Control

  • Anonymous uploads have separate endpoints and permissions
  • Member uploads require authentication
  • File types can be restricted by upload type (anonymous/member/both)
  • File size limits are enforced per file type

Data Protection

  • File hashes (MD5, SHA1) are calculated for integrity verification
  • Files are stored with unique generated names to prevent collisions
  • Original filenames are preserved in the database
  • User tracking for authenticated uploads
  • IP address tracking for security auditing

Best Practices

  1. Always validate file types on the server side
  2. Set appropriate file size limits
  3. Regularly clean up anonymous files
  4. Monitor file statistics for unusual activity
  5. Use HTTPS for file uploads
  6. Consider implementing virus scanning for uploaded files

Dependencies

This bundle requires:

  • PHP ^8.1
  • Symfony ^6.4
  • Doctrine ORM ^2.0 || ^3.0
  • League Flysystem ^3.0
  • Symfony String Component

Bundle dependencies:

  • tourze/doctrine-ip-bundle
  • tourze/doctrine-timestamp-bundle
  • tourze/doctrine-track-bundle
  • tourze/doctrine-user-bundle
  • tourze/doctrine-snowflake-bundle

Advanced Usage

Event Listeners

You can listen to file upload events:

namespace App\EventListener;

use Tourze\FileStorageBundle\Event\FileUploadedEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

#[AsEventListener(event: FileUploadedEvent::class)]
class FileUploadListener
{
    public function __invoke(FileUploadedEvent $event): void
    {
        $file = $event->getFile();
        // Custom logic: virus scan, image optimization, etc.
    }
}

Custom File Validators

Extend the validation logic:

namespace App\Validator;

use Symfony\Component\HttpFoundation\File\UploadedFile;
use Tourze\FileStorageBundle\Validator\FileValidatorInterface;

class VirusScanValidator implements FileValidatorInterface
{
    public function validate(UploadedFile $file): void
    {
        // Implement virus scanning logic
        if ($this->hasVirus($file)) {
            throw new FileValidationException('File contains malware');
        }
    }
}

Testing

The bundle includes comprehensive tests with full coverage:

# Run all tests
./vendor/bin/phpunit packages/file-storage-bundle/tests

# Run with coverage
./vendor/bin/phpunit packages/file-storage-bundle/tests --coverage-html coverage

Test Suite Results:

  • 📊 128 tests, 424 assertions
  • All tests passing
  • 🧪 100% test coverage for critical components
  • 🎯 Unit + Integration tests for controllers, services, repositories, and commands

PHPStan Analysis

Static analysis with PHPStan level 5:

php -d memory_limit=2G ./vendor/bin/phpstan analyse packages/file-storage-bundle

Analysis Results:

  • 0 errors - Clean code with proper type declarations
  • 🔒 Level 5 - Strict type checking enabled
  • 📝 Full documentation - All public methods documented

License

This bundle is released under the MIT License. See the LICENSE file for details.

tourze/file-storage-bundle 适用场景与选型建议

tourze/file-storage-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.17k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 11 月 01 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 tourze/file-storage-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 tourze/file-storage-bundle 我们能提供哪些服务?
定制开发 / 二次开发

基于 tourze/file-storage-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1.17k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 18
  • 依赖项目数: 9
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-11-01