You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 3.4+Gaufrette处理谷歌存储EPUB文件的读写与上传问题

解决EPUB文件上传到谷歌存储的问题(Symfony 3.4 + Gaufrette 0.3.0)

首先得说,你给出的UploadedFile信息里,error = 1是核心问题——这对应PHP的UPLOAD_ERR_INI_SIZE常量,意思是上传的EPUB文件超过了PHP配置的大小限制,这才导致文件没有路径、大小为0,后续的file_get_contents自然会报错。咱们先把本地上传的坑填上,再一步步处理谷歌存储的上传和读取。

第一步:修复本地文件上传的大小限制问题

你需要调整几个关键配置项:

  • 打开php.ini,找到upload_max_filesize,把它改成比你的EPUB文件大的值,比如20M(根据实际文件大小调整)
  • 同时把post_max_size设得比upload_max_filesize大一点,比如25M,因为POST请求的总大小不能超过这个值
  • 如果用的是Nginx服务器,还要检查nginx.conf里的client_max_body_size,同样设成大于文件大小的值

改完之后重启你的Web服务器(Apache/Nginx)和PHP-FPM(如果用的话),这样文件才能正常传到服务器的临时目录。

第二步:用Gaufrette把EPUB传到谷歌存储

当文件能正常上传到本地后,咱们再用Gaufrette的谷歌存储适配器处理云端上传。

1. 配置Gaufrette的谷歌存储适配器

在config.yml里添加如下配置:

knp_gaufrette:
    adapters:
        google_cloud_storage:
            google_cloud_storage:
                project_id: '你的谷歌云项目ID'
                key_file: '%kernel.root_dir%/config/google-service-account-key.json' # 替换成你的服务账号密钥文件路径
                bucket_name: '你的存储桶名称'
    filesystems:
        gcs_media:
            adapter: google_cloud_storage

2. 编写控制器的上传逻辑

这里给你一个包含验证和上传的完整示例:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Knp\Bundle\GaufretteBundle\FilesystemMap;
use Symfony\Component\HttpFoundation\JsonResponse;

class EpubUploadController extends Controller
{
    public function uploadAction(Request $request, FilesystemMap $filesystemMap)
    {
        /** @var UploadedFile $epubFile */
        $epubFile = $request->files->get('epub_file'); // 对应你表单里的文件字段名

        // 先检查文件是否有效上传
        if (!$epubFile || $epubFile->getError() !== UPLOAD_ERR_OK) {
            return new JsonResponse(['error' => '文件上传失败,请检查文件大小是否超出限制'], 400);
        }

        // 可选:验证文件类型,确保是EPUB
        if ($epubFile->getMimeType() !== 'application/epub+zip') {
            return new JsonResponse(['error' => '请上传有效的EPUB文件'], 400);
        }

        // 获取Gaufrette的谷歌存储文件系统实例
        $gcsFilesystem = $filesystemMap->get('gcs_media');

        // 生成唯一存储文件名(避免重名覆盖)
        $storageFileName = uniqid('epub_') . '.' . $epubFile->guessExtension();

        // 上传文件到谷歌存储——大文件建议用流式上传(见下方提示)
        $fileContent = file_get_contents($epubFile->getRealPath());
        $gcsFilesystem->write($storageFileName, $fileContent);

        // 如果存储桶允许公开访问,生成公开URL
        $publicUrl = sprintf('https://storage.googleapis.com/%s/%s', '你的存储桶名称', $storageFileName);

        return new JsonResponse([
            'status' => 'success',
            'storage_filename' => $storageFileName,
            'public_url' => $publicUrl
        ]);
    }
}

提示:如果EPUB文件很大(比如超过100M),用file_get_contents可能占满内存,改用流式上传更稳妥:

$fileStream = $epubFile->openFile('r');
$gcsFilesystem->writeStream($storageFileName, $fileStream);

第三步:从谷歌存储读取EPUB文件

读取方式分两种,按需选择:

1. 通过Gaufrette读取并返回下载响应

适合需要权限验证的场景:

use Knp\Bundle\GaufretteBundle\FilesystemMap;
use Symfony\Component\HttpFoundation\Response;

class EpubDownloadController extends Controller
{
    public function downloadAction(FilesystemMap $filesystemMap, $fileName)
    {
        $gcsFilesystem = $filesystemMap->get('gcs_media');

        if (!$gcsFilesystem->has($fileName)) {
            throw $this->createNotFoundException('该EPUB文件不存在');
        }

        // 获取文件内容
        $epubContent = $gcsFilesystem->read($fileName);

        // 返回下载响应
        return new Response(
            $epubContent,
            200,
            [
                'Content-Type' => 'application/epub+zip',
                'Content-Disposition' => sprintf('attachment; filename="%s"', $fileName)
            ]
        );
    }
}

2. 直接通过公开URL访问

如果存储桶设置了对象公开可读权限,用户可以直接用之前生成的publicUrl访问或下载文件。如果需要私有访问,可以用谷歌云的签名URL功能,Gaufrette的谷歌适配器也支持生成签名URL,你可以查阅相关文档实现。

最后几个注意点

  • 确保你的谷歌服务账号拥有存储桶的读写权限,不然上传下载都会失败
  • 表单提交时一定要加enctype="multipart/form-data",否则文件根本传不上去
  • 如果遇到权限问题,检查谷歌云控制台里存储桶的权限设置,确认服务账号的角色配置正确

内容的提问来源于stack exchange,提问作者shuba.ivan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:48:06