neam / dna-project-base-stateless-file-management
添加模式并封装了受12因素启发的[DNA Project Base](http://neamlabs.com/dna-project-base/)无状态文件处理逻辑的帮助特质
Requires
- php: >=5.6.5
- ext-iconv: *
- filestack/filestack-php: >=1.1.11
- league/flysystem: ~1.0.24
- league/flysystem-aws-s3-v3: ~1.0.13
- propel/propel: *@dev
Requires (Dev)
- codeception/codeception: ~2.2.4
This package is not auto-updated.
Last update: 2024-09-14 19:09:34 UTC
README
添加模式并封装DNA Project Base无状态文件处理逻辑的帮助特质。
而不是在数据模型的项目中存储路径或uris,需要跟踪文件的项目将使用对文件项类型的关联,它反过来又有关系到指定文件二进制副本存储位置的文件实例项。
功能
- 在PHP应用程序中抽象无状态文件管理
- 存储远程可用的文件元数据,因此可以在不访问文件的情况下执行文件查询
- 仅将本地文件系统用作短暂的、单事务的缓存,例如下载大文件、操作它并将操作结果存储在数据库中/上传文件的修改版本。
- 使用Filestack.com作为安全远程文件存储
- 启用使用Filestack.com的部件和JS SDK进行基于浏览器的文件上传
- 启用使用Filestack.com的文件转换API
- 能够将公共文件推送到S3存储桶,以便其他人可以访问
背景和动机
以下来自https://12factor.net/processes的引用描述了这种方法的动机
Twelve-factor processes are stateless and share-nothing. Any data that needs to persist must be stored in a stateful backing service, typically a database.
The memory space or filesystem of the process can be used as a brief, single-transaction cache. For example, downloading a large file, operating on it, and storing the results of the operation in the database. The twelve-factor app never assumes that anything cached in memory or on disk will be available on a future request or job – with many processes of each type running, chances are high that a future request will be served by a different process. Even when running only one process, a restart (triggered by code deploy, config change, or the execution environment relocating the process to a different physical location) will usually wipe out all local (e.g., memory and filesystem) state.
设计原则
这些帮助特质建立的一些原则
- 本地文件操作应通过读取LOCAL_TMP_FILES_PATH . DIRECTORY_SEPARATOR . $file->getPath()简单地实现,如getLocalAbsolutePath()中定义的那样
- 文件的路径相对于存储组件的文件系统,应遵循格式$file->getId() . DIRECTORY_SEPARATOR . $file->getFilename() - 这是文件的“正确路径”,确保可以将具有相同名称的多个文件写入所有文件系统
- 运行$file->ensureCorrectLocalFile()确保§1和§2(设计在本地文件操作之前、文件创建/修改时间之后以及/或作为计划任务运行)
- 文件实例记录告诉我们文件二进制副本的存储位置
- 文件实例应(如果可能)使用由$file->getPath()提供的相对路径存储其二进制副本,以便检索文件的二进制内容是直接的,并且最终的公共URL遵循由$file->getPath()提供的官方路径/名称
此特质处理的当前存储组件
- local(意味着二进制存储在本地)
- filestack(意味着二进制存储在filestack)
- filestack-pending(意味着二进制正在等待异步任务完成,之后该实例将转换为'filestack'实例)
- filepicker(旧版filestack名称,仅用于服务filepicker存储的文件,直到所有文件都已转换为filestack-resources)
- public-files-s3(意味着二进制存储在公开可访问的Amazon S3存储桶中)
安装
-
将文件和file_instance表模式复制到您的schema.xml中,并生成新的propel模型
-
将
\neam\stateless_file_management\FileTrait
特性添加到File模型class File extends BaseFile { use \neam\stateless_file_management\FileTrait; }
-
无论您的数据模型何时需要文件,都应将外键关系添加到文件表中,参见schema.xml中的example_item_type以获取示例。
-
在您的应用程序中设置以下常量
LOCAL_TMP_FILES_PATH
- 一个路径,其中租户的本地临时文件可以由php进程写入和读取
DATA
- 数据集ID,对应于当前请求中使用的数据库。允许为多个租户共享相同的后端文件服务
可选地也可以设置以下
PUBLIC_FILES_S3_BUCKET
- 公共共享文件存储的Amazon S3存储桶,以's3://'前缀开头
PUBLIC_FILES_S3_REGION
- S3存储桶所在的地区
PUBLIC_FILES_S3_PATH
- 公共共享文件存储在Amazon S3存储桶中的目录。如果整个存储桶都用于存储文件,则留空。(示例:"/files/",在这种情况下,租户文件将发布到"/files/%DATA/"而不是"/%DATA")
PUBLIC_FILES_S3_HTTP_HOST
- 存储桶通过http和https可用的主机名(默认为从开头移除's3://'的存储桶名称)
PUBLIC_FILE_UPLOADERS_ACCESS_KEY
- 访问上述存储桶的Amazon S3访问密钥
PUBLIC_FILE_UPLOADERS_SECRET
- 访问上述存储桶的Amazon S3访问密钥
FILESTACK_API_KEY
- Filestack.com API密钥
FILESTACK_API_SECRET
- 用于为安全的Filestack资源临时签名URL
CONTEXT_IO_API_SECRET
- 用于为安全的Context.IO资源临时签名URL
APPVHOST
- 当前部署使用的主机名(以便能够引用REST API端点)
注意:DNA项目基础使用PHP App Config根据预期的配置环境变量设置常量。
用法
使用远程存储的文件本地的示例
$exampleItemType = \propel\models\ExampleItemTypeQuery::create()->findPk(1);
$fooFile = $exampleItemType->getFileRelatedByFooFileId();
$fooFileName = $fooFile->getFilename();
$mimeType = $fooFile->getMimetype();
switch ($mimeType) {
case 'text/plain':
case 'text/csv':
case 'application/vnd.ms-excel':
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
// Actually downloads the file
$fooFilePath = $fooFile->getAbsoluteLocalPath();
// Example of using the file contents in a PHP library that expects an absolute path to a local file
$cellData = SpreadsheetDataFileHelper::getSpreadsheetCellData($fooFilePath);
// ...
break;
default:
throw new Exception("Unsupported mimetype ('$mimeType')");
break;
}
创建本地文件并确保其作为公共文件存储在远程的示例
$exampleItemType = \propel\models\ExampleItemTypeQuery::create()->findPk(1);
// Create new File record with sample file contents as a local file instance
$fooFile = new File();
$fooFile->setFilename('foo.txt');
$fooFile->putContents("text file contents\ntext file contents");
// Sync to public files
$fooFile->ensureRemotePublicFileInstance();
// Save in the parent item only after we have stored a remote copy of the file contents
$exampleItemType->setFileRelatedByFooFileId($fooFile);
$exampleItemType->save();
// Access public url
$publicUrl = $fooFile->fileInstanceAbsoluteUrl($fooFile->getFileInstanceRelatedByPublicFilesS3FileInstanceId());