2

我目前正在为某些插件编写一个记录器,写入 ILIAS 中相当大的日志文件。我正在使用整洁的新文件系统。由于新的日志消息需要附加到文件中,我不能简单地使用 put 或 update,因为它们似乎总是截断日志文件。Flysystem 似乎不支持简单的附加命令,所以我发现一种可行的方法如下:

$old_data = "";
if ($DIC->filesystem()->storage()->has($this->path)) {
    $old_data = $DIC->filesystem()->storage()->read($this->path);
}
$DIC->filesystem()->storage()->put($this->path, $old_data.$string);

但是,如果将大量数据附加到日志中,这对于 IO 来说似乎非常昂贵。我想,这最好使用流来完成。我的文档(https://github.com/ILIAS-eLearning/ILIAS/tree/release_5-3/src/Filesystem)我发现了以下内容:

$webDataRoot = $DIC->filesystem()->web();
$fileStream = $webDataRoot->readStream('relative/path/to/file');

//seek at the end of the stream
$fileStream->seek($fileStream->getSize() - 1);
//append something
$fileStream->write("something");

但是,有了这个,我得到了Can not write to a non-writable stream异常。看来,我需要像这样打开流:

$resource = fopen('myPath', 'rw');

但是,文档中特别不鼓励这样做。通过使用 ILIAS 中的文件系统来解决这个问题的最佳方法是什么?

4

1 回答 1

3

问题

ILIAS 的文件系统抽象利用 flysystem 来操作文件系统。但是,正如您已经指出的那样,flysystem 没有提供将数据附加到文件的简单方法。主要原因似乎是许多用于将文件写入存储后端的文件系统适配器由于底层技术不支持追加操作,例如重新上传整个文件的S3 V3 存储适配器.

不幸的是,位于 ( ILIAS-eLearning ) 的文档是错误的,因为 flysystem 返回的流是只读的,因为某些文件系统适配器仅“模拟”文件流的行为。该流指向本地副本或内存流,而不是位于存储后端的“真实”文件,请参阅Flysystem AWS S3 适配器

结论

总之,使用当前 ILIAS 文件系统实现没有正确的方法将数据附加到现有文件,因为 flyway 不提供此类操作。此外,即使 flyway 提供,一些存储后端仍然不支持此类操作。一个很好的例子是 AWS S3 存储后端,请参阅问题41783903的答案。

您的用例的可能解决方法

如果您能够使用多个日志文件,请使用某种日志文件轮换来减少 IO,这不是解决方案,但有助于将负载至少保持在一致的水平。例如,如果大小超过 20MB,则写入新的日志文件并保留最后 20 个日志文件。

于 2018-07-04T17:19:24.057 回答