根据会话id配置服务



在我的Symfony 6项目中,我需要在每个用户会话中存储上传的大文件。

由于直接将这些文件存储在会话中不是一个好主意,我使用的flysystem具有每个会话id的目录和清理过程。

到目前为止还不错

现在,由于我不想每次使用当前会话id作为基本目录直接配置flysystem存储作为服务时都生成每个会话id的文件路径,如下所示:

flysystem:
storages:
session.storage:
adapter: 'local'
options:
directory: '%env(APP_SESSION_STORAGE_PATH)%/%sessionId%'

这显然不起作用,因为没有%sessionId%,但我如何才能做到这一点?

我也尝试过使用工厂,但这也感觉过于复杂,因为我必须从flysystem-bundle复制逻辑来初始化此服务。

我知道这个服务只在http上下文中工作。

只是代码的想法。就在你的";。。必须从flysystem捆绑包中复制逻辑&";。哇!我认为你试图克服复杂的

我不知道你的应用程序逻辑。然而就像:

// config/services.yaml
services:
_defaults:
//..
bind:
$bigFileSessionStoragePath: '%env(APP_SESSION_BIG_FILE_STORAGE_PATH)%'

您的服务:

// BigFileSessionStorage.php

namespace Acme/Storage;
use SymfonyComponentFilesystemFilesystem;
use SymfonyComponentHttpFoundationFileFile;
use SymfonyComponentHttpFoundationRequestStack;
class BigFileSessionStorage
{
private string $bigFileSessionDirPath;
public function __construct(
private RequestStack $requestStack,
private Filesystem $filesystem,
private string $bigFileSessionStoragePath
){}
public function storeBigSessionFile(File $bigSessionFile){
$sessionBifFileDir = $this->getBigFileSessionDirectory();
// move a Big File ..
$this->filesystem->copy(...)
}
public function getBigFileSessionDirectory(): string{
$sessionId = $this->requestStack->getSession()->getId();
$path = $this->bigFileSessionDirPath.DIRECTORY_SEPARATOR.$sessionId;
if (!$this->filesystem->exists($path)){
$this->filesystem->mkdir($path);
$this->bigFileSessionDirPath = $path;
}
return $this->bigFileSessionDirPath;
}
// TODO & so on 
public function removeBigFileSessionDirectory(){}  

}

然后在你需要的地方注入这个服务。

基于@voodoo417答案的想法,我最终为FilesystemOperator创建了一个装饰器。我对这个解决方案不太满意,因为它包含了很多样板装饰器代码,只是为了修改根目录,在那里可以首先配置根目录。

但它是有效的,结果正是我想要的。

flysystem:
storages:
baseSession.storage:
adapter: 'local'
options:
directory: '%env(APP_SESSION_STORAGE_PATH)%'
class SessionStorage implements FilesystemOperator
{
public function __construct(
private FilesystemOperator $baseSessionStorage,
private RequestStack       $requestStack,
) {}
private function chroot(string $location): string
{
$session   = $this->requestStack->getSession();
$sessionId = $session->getId();
// TODO: Don't allow /../ syntax to access other sessions
return "/{$sessionId}/" . ltrim($location, '/');
}
public function fileExists(string $location): bool
{
return $this->baseSessionStorage->fileExists($this->chroot($location));
}
// ... decorate all the other methods of FilesystemOperator
}

现在,我可以在应用程序中的任何位置(在http上下文中(使用SessionStorage,并且可以在控制台命令(cron(中使用FilesystemOperator $baseSessionStorage来清理文件。

相关内容

  • 没有找到相关文章

最新更新