PHP项目Symfony文件系统操作

wen PHP项目 2

本文目录导读:

PHP项目Symfony文件系统操作

  1. 基础组件:Filesystem组件
  2. 在Controller中使用
  3. 流式文件处理(大文件)
  4. 路径处理
  5. 安全文件上传
  6. 处理上传文件(完整示例)
  7. 配置文件服务
  8. 最佳实践
  9. 性能优化建议

在Symfony PHP框架中,文件系统操作主要通过几个核心组件实现,以下是完整指南:

基础组件:Filesystem组件

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
$filesystem = new Filesystem();

常用方法示例

// 创建目录
$filesystem->mkdir('/tmp/random/dir/' . uniqid());
// 创建文件(带内容)
$filesystem->touch('/tmp/file.txt');
$filesystem->dumpFile('/tmp/file.txt', '文件内容');
// 复制/移动
$filesystem->copy('/tmp/source.txt', '/tmp/target.txt');
$filesystem->rename('/tmp/old.txt', '/tmp/new.txt');
// 删除
$filesystem->remove(['/tmp/file.txt', '/tmp/dir']);
// 检查是否存在
$filesystem->exists('/tmp/file.txt');
// 权限设置
$filesystem->chmod('/tmp/file.txt', 0644);
// 创建符号链接
$filesystem->symlink('/path/to/source', '/path/to/link');
// 镜像目录
$filesystem->mirror('/source/dir', '/target/dir');

在Controller中使用

// src/Controller/FileController.php
namespace App\Controller;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class FileController extends AbstractController
{
    #[Route('/file/upload', name: 'file_upload')]
    public function upload(Request $request, Filesystem $filesystem): Response
    {
        /** @var UploadedFile $file */
        $file = $request->files->get('file');
        if ($file) {
            $uploadsDir = $this->getParameter('kernel.project_dir') . '/public/uploads';
            // 确保目录存在
            $filesystem->mkdir($uploadsDir);
            $newFilename = uniqid() . '.' . $file->guessExtension();
            try {
                $file->move($uploadsDir, $newFilename);
                return $this->json([
                    'path' => '/uploads/' . $newFilename
                ]);
            } catch (FileException $e) {
                return $this->json(['error' => $e->getMessage()], 400);
            }
        }
        return $this->render('file/upload.html.twig');
    }
}

流式文件处理(大文件)

use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
// 使用Stream处理大文件
$filesystem = new Filesystem();
// 追加写入(不覆盖)
$filesystem->appendToFile('/tmp/log.txt', "New log entry\n");
// 使用dumpFile替代file_put_contents
$filesystem->dumpFile('/tmp/large.json', json_encode($largeArray));
// 文件读取
$content = file_get_contents('/tmp/file.txt'); // PHP原生

路径处理

use Symfony\Component\Filesystem\Path;
// 跨平台路径处理
$path = Path::normalize('/var//www/../uploads/./file.txt');
// 结果: /var/uploads/file.txt
// 获取相对路径
$relativePath = Path::makeRelative('/var/www/uploads/file.txt', '/var/www');
// 结果: uploads/file.txt
// 获取路径的不同部分
Path::getFilename('/var/www/file.txt');     // file.txt
Path::getDirectory('/var/www/file.txt');    // /var/www
Path::getExtension('/var/www/file.txt');    // txt

安全文件上传

// src/Service/FileUploader.php
namespace App\Service;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\String\Slugger\SluggerInterface;
class FileUploader
{
    private $targetDirectory;
    private $slugger;
    private $filesystem;
    public function __construct(
        string $targetDirectory,
        SluggerInterface $slugger,
        Filesystem $filesystem
    ) {
        $this->targetDirectory = $targetDirectory;
        $this->slugger = $slugger;
        $this->filesystem = $filesystem;
    }
    public function upload(UploadedFile $file): string
    {
        // 生成安全文件名
        $originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
        $safeFilename = $this->slugger->slug($originalFilename);
        $newFilename = $safeFilename . '-' . uniqid() . '.' . $file->guessExtension();
        try {
            $file->move($this->getTargetDirectory(), $newFilename);
        } catch (FileException $e) {
            throw new \RuntimeException('文件上传失败: ' . $e->getMessage());
        }
        return $newFilename;
    }
    public function getTargetDirectory(): string
    {
        return $this->targetDirectory;
    }
}

处理上传文件(完整示例)

// src/Controller/MediaController.php
#[Route('/media/upload', name: 'media_upload')]
public function uploadMedia(Request $request): Response
{
    $uploadedFile = $request->files->get('media');
    // 验证文件类型
    $allowedMimeTypes = ['image/jpeg', 'image/png', 'application/pdf'];
    if (!in_array($uploadedFile->getMimeType(), $allowedMimeTypes)) {
        return $this->json(['error' => '不支持的文件类型'], 400);
    }
    // 验证文件大小 (5MB)
    if ($uploadedFile->getSize() > 5 * 1024 * 1024) {
        return $this->json(['error' => '文件过大(最大5MB)'], 400);
    }
    try {
        $newFilename = $this->fileUploader->upload($uploadedFile);
        return $this->json(['url' => '/uploads/' . $newFilename]);
    } catch (\Exception $e) {
        return $this->json(['error' => '上传失败'], 500);
    }
}

配置文件服务

# config/services.yaml
services:
    App\Service\FileUploader:
        arguments:
            $targetDirectory: '%kernel.project_dir%/public/uploads'

最佳实践

错误处理

try {
    $filesystem->copy($source, $target);
} catch (IOExceptionInterface $exception) {
    echo "操作失败: " . $exception->getPath();
}

权限设置

// 递归设置目录权限
$filesystem->chmod(new \SplFileInfo('/path/to/dir'), 0755, 0000, true);

临时文件处理

// 使用系统临时目录
$tempFile = tempnam(sys_get_temp_dir(), 'symfony');
$filesystem->dumpFile($tempFile, $data);
// 使用完毕后清理
$filesystem->remove($tempFile);

性能优化建议

  1. 大量小文件操作:考虑使用dumpFile替代逐个touch+file_put_contents
  2. 目录遍历:使用Finder组件替代手动递归
  3. 文件锁定:需要并发写入时使用flock
  4. 内存管理:处理大文件时使用流而不是一次性读取

通过Symfony的Filesystem组件,你可以安全高效地完成所有标准文件系统操作,同时保持代码的可读性和跨平台兼容性。

抱歉,评论功能暂时关闭!