Public 和 SonataMediaBundle 的私人媒体上传到不同的文件夹(网络和私人)
Public and private Media of SonataMediaBundle uploaded in different folders (web and private)
我正在使用 SonataMediaBundle,直到现在我一直在 Symfony 的 web
文件夹中上传文件 publicly。这是我的配置文件的一部分:
contexts:
default: # the default context is mandatory
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
- sonata.media.provider.file
- sonata.media.provider.vimeo
formats:
small: { width: 100 , quality: 70}
big: { width: 500 , quality: 70}
profile_pics: # the default context is mandatory
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
- sonata.media.provider.file
- sonata.media.provider.vimeo
formats:
small: { width: 100 , quality: 70}
big: { width: 500 , quality: 70}
cdn:
server:
path: %cdn_server_path% # http://media.sonata-project.org/
filesystem:
local:
directory: %kernel.root_dir%/../web/uploads/media
create: false
在我的 parameters.yml
中我有 cdn_server_path: /uploads/media/
.
这将上传 web/uploads/media/contextname/0001/01/***
中的文件。
在 public 文件夹中,每个人都可以看到这些文件。我知道我可以在 app/Resources/
中的某处更改此文件夹,但这会使我的所有文件成为私有文件,这是我不想要的。通过私有,我的意思是它们应该以某种方式由控制器提供服务。
如何将一些文件 public 和其他文件分开?有没有办法让某个上下文上传文件不同于另一个?或者其他方式?
此外,当上传文件到app/Resources文件夹时,无法预览,因为它们的url变成了http://website.com/app/Resources/media/profile_pics/0001/01/85e05ab9685b1745af4e64ff98ef91eed6e4ccdf.jpeg而不是public,因为它不在web 文件夹,Symfony 仅有的 public 个文件。这怎么能做到?
EDIT: 我已经成功完成了上传部分(查看下面的答案),但检索部分有点麻烦。我还在寻找方法。
好的,我快到了。我的文件正在上传到我想要的任何文件夹,但我无法显示它们。
我们的想法是创建一个自定义提供程序,它有自己的文件系统和适配器服务。问题是我需要将要上传文件的文件夹传递给适配器服务。该适配器被传递给文件系统,然后文件系统被传递给提供者。 SonataMediaBundle 的问题在于它不允许您修改适配器的目录,因此您必须创建自己的目录并将其一直传递给您的提供商。
服务:
sonata.media.provider.private:
class: MedAppBundle\Services\PrivateFilesProvider
tags:
- { name: sonata.media.provider }
arguments: [%private_provider_name%,@medapp_private.filesystem,@sonata.media.cdn.server,@sonata.media.generator.default,@sonata.media.thumbnail.format]
medapp_private.filesystem:
class: MedAppBundle\Services\PrivateFilesystem
arguments: [@medapp_private.adapter]
medapp_private.adapter:
class: MedAppBundle\Services\PrivateFileAdapter
arguments: [%private_filesystem_directory%,true]
parameters.yml
private_filesystem_directory: %kernel.root_dir%/Resources/media
private_provider_name: sonata.media.provider.private
自定义适配器
use Sonata\MediaBundle\Filesystem\Local;
class PrivateFileAdapter extends Local
{
}
文件系统
use Gaufrette\Filesystem;
class PrivateFilesystem extends Filesystem
{
}
最后,提供商
use Application\Sonata\MediaBundle\Entity\Media;
use Gaufrette\Filesystem;
use Sonata\MediaBundle\CDN\CDNInterface;
use Sonata\MediaBundle\Generator\GeneratorInterface;
use Sonata\MediaBundle\Provider\FileProvider;
use Sonata\MediaBundle\Thumbnail\ThumbnailInterface;
class PrivateFilesProvider extends FileProvider
{
public function getPrivateMedia(Media $media)
{
// $path = $this->generatePublicUrl($media, 'reference');
// $ppath = $this->generatePrivateUrl($media, "reference");
$content = $this->getReferenceFile($media)->getContent();
header('Content-Type: ' . $media->getContentType());
return 'data:' . $media->getContentType() . ';base64,' . base64_encode($content);
}
}
然后,将此提供程序添加到您的任何 sonata_media 上下文中。我已将其添加到默认上下文中,例如:
sonata_media:
db_driver: doctrine_orm
default_context: default
contexts:
default:
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
- sonata.media.provider.file
- sonata.media.provider.vimeo
- sonata.media.provider.private
要在私人文件夹中创建新媒体:
$media = new Media();
$media->setBinaryContent($file);
$media->setContext('default');
$media->setProviderName('sonata.media.provider.private');
$this->em->persist($media);
$this->em->flush();
$file 是来自您的表单的文件内容。
这将创建用于上传文件的文件夹 app\Resources\media\default[=18=]01
。
现在的问题是检索它们,因为它们没有 public link 并且需要在控制器中检索。我在提供程序中创建了一个 getPrivateMedia() 方法,但它没有按预期工作。
编辑:
注意到服务也可以这样定义:
sonata.media.provider.private:
class: MedAppBundle\Services\PrivateFilesProvider
tags:
- { name: sonata.media.provider }
arguments: [%private_provider_name%,@medapp_private.filesystem,@sonata.media.cdn.server,@sonata.media.generator.default,@sonata.media.thumbnail.format,%kernel.root_dir%]
medapp_private.filesystem:
class: Gaufrette\Filesystem
arguments: [@medapp_private.adapter]
medapp_private.adapter:
class: Sonata\MediaBundle\Filesystem\Local
arguments: [%private_filesystem_directory%,true]
无需为提供程序创建自定义文件系统或适配器,只需创建新服务并将目录传递给适配器,然后将适配器传递给文件系统,再将文件系统传递给自定义提供程序。这是在您不需要任何自定义功能的情况下。
我遇到了完全相同的问题,非常感谢上传解决方案。
从安全目录下载文件 - sonata 提供了一种方法,因此您甚至不需要此处概述的自定义提供程序:https://sonata-project.org/bundles/media/master/doc/reference/security.html
我的实现是这样的:
services:
sonata.media.provider.private:
class: Sonata\MediaBundle\Provider\FileProvider
tags:
- { name: sonata.media.provider }
arguments:
- 'sonata.media.provider.private'
- '@app.sonata.media.private.filesystem'
- '@sonata.media.cdn.server'
- '@sonata.media.generator.default'
- '@sonata.media.thumbnail.format'
app.sonata.media.private.filesystem:
class: Gaufrette\Filesystem
arguments: ['@app.sonata.media.private.adapter']
app.sonata.media.private.adapter:
class: Sonata\MediaBundle\Filesystem\Local
arguments:
- "%kernel.root_dir%/../doclib/uploads"
- true
具有明确定义的安全策略的上下文以控制谁可以访问文件。本例中的超级管理员:
sonata_media:
contexts:
privatefiles:
download:
strategy: sonata.media.security.superadmin_strategy
mode: http
providers:
- sonata.media.provider.private
在 twig 中,您可以获得可下载资源的链接,如下所示:
{{ path('sonata_media_download', { 'id':media|sonata_urlsafeid }) }}
sonata_media_download
映射 MediaController::downloadAction()
,它实现了您试图通过 getPrivateMedia()
.
实现的功能
我现在坚持的一点是为新提供者设置 allowed_extensions
等内容,因为 providers
部分不接受 private
作为名称,所以我假设这个需要在某处具体定义。
编辑: allowed_extensions
等可以通过自定义提供程序服务定义作为进一步的参数传递。
我正在使用 SonataMediaBundle,直到现在我一直在 Symfony 的 web
文件夹中上传文件 publicly。这是我的配置文件的一部分:
contexts:
default: # the default context is mandatory
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
- sonata.media.provider.file
- sonata.media.provider.vimeo
formats:
small: { width: 100 , quality: 70}
big: { width: 500 , quality: 70}
profile_pics: # the default context is mandatory
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
- sonata.media.provider.file
- sonata.media.provider.vimeo
formats:
small: { width: 100 , quality: 70}
big: { width: 500 , quality: 70}
cdn:
server:
path: %cdn_server_path% # http://media.sonata-project.org/
filesystem:
local:
directory: %kernel.root_dir%/../web/uploads/media
create: false
在我的 parameters.yml
中我有 cdn_server_path: /uploads/media/
.
这将上传 web/uploads/media/contextname/0001/01/***
中的文件。
在 public 文件夹中,每个人都可以看到这些文件。我知道我可以在 app/Resources/
中的某处更改此文件夹,但这会使我的所有文件成为私有文件,这是我不想要的。通过私有,我的意思是它们应该以某种方式由控制器提供服务。
如何将一些文件 public 和其他文件分开?有没有办法让某个上下文上传文件不同于另一个?或者其他方式?
此外,当上传文件到app/Resources文件夹时,无法预览,因为它们的url变成了http://website.com/app/Resources/media/profile_pics/0001/01/85e05ab9685b1745af4e64ff98ef91eed6e4ccdf.jpeg而不是public,因为它不在web 文件夹,Symfony 仅有的 public 个文件。这怎么能做到?
EDIT: 我已经成功完成了上传部分(查看下面的答案),但检索部分有点麻烦。我还在寻找方法。
好的,我快到了。我的文件正在上传到我想要的任何文件夹,但我无法显示它们。
我们的想法是创建一个自定义提供程序,它有自己的文件系统和适配器服务。问题是我需要将要上传文件的文件夹传递给适配器服务。该适配器被传递给文件系统,然后文件系统被传递给提供者。 SonataMediaBundle 的问题在于它不允许您修改适配器的目录,因此您必须创建自己的目录并将其一直传递给您的提供商。
服务:
sonata.media.provider.private:
class: MedAppBundle\Services\PrivateFilesProvider
tags:
- { name: sonata.media.provider }
arguments: [%private_provider_name%,@medapp_private.filesystem,@sonata.media.cdn.server,@sonata.media.generator.default,@sonata.media.thumbnail.format]
medapp_private.filesystem:
class: MedAppBundle\Services\PrivateFilesystem
arguments: [@medapp_private.adapter]
medapp_private.adapter:
class: MedAppBundle\Services\PrivateFileAdapter
arguments: [%private_filesystem_directory%,true]
parameters.yml
private_filesystem_directory: %kernel.root_dir%/Resources/media
private_provider_name: sonata.media.provider.private
自定义适配器
use Sonata\MediaBundle\Filesystem\Local;
class PrivateFileAdapter extends Local
{
}
文件系统
use Gaufrette\Filesystem;
class PrivateFilesystem extends Filesystem
{
}
最后,提供商
use Application\Sonata\MediaBundle\Entity\Media;
use Gaufrette\Filesystem;
use Sonata\MediaBundle\CDN\CDNInterface;
use Sonata\MediaBundle\Generator\GeneratorInterface;
use Sonata\MediaBundle\Provider\FileProvider;
use Sonata\MediaBundle\Thumbnail\ThumbnailInterface;
class PrivateFilesProvider extends FileProvider
{
public function getPrivateMedia(Media $media)
{
// $path = $this->generatePublicUrl($media, 'reference');
// $ppath = $this->generatePrivateUrl($media, "reference");
$content = $this->getReferenceFile($media)->getContent();
header('Content-Type: ' . $media->getContentType());
return 'data:' . $media->getContentType() . ';base64,' . base64_encode($content);
}
}
然后,将此提供程序添加到您的任何 sonata_media 上下文中。我已将其添加到默认上下文中,例如:
sonata_media:
db_driver: doctrine_orm
default_context: default
contexts:
default:
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
- sonata.media.provider.file
- sonata.media.provider.vimeo
- sonata.media.provider.private
要在私人文件夹中创建新媒体:
$media = new Media();
$media->setBinaryContent($file);
$media->setContext('default');
$media->setProviderName('sonata.media.provider.private');
$this->em->persist($media);
$this->em->flush();
$file 是来自您的表单的文件内容。
这将创建用于上传文件的文件夹 app\Resources\media\default[=18=]01
。
现在的问题是检索它们,因为它们没有 public link 并且需要在控制器中检索。我在提供程序中创建了一个 getPrivateMedia() 方法,但它没有按预期工作。
编辑: 注意到服务也可以这样定义:
sonata.media.provider.private:
class: MedAppBundle\Services\PrivateFilesProvider
tags:
- { name: sonata.media.provider }
arguments: [%private_provider_name%,@medapp_private.filesystem,@sonata.media.cdn.server,@sonata.media.generator.default,@sonata.media.thumbnail.format,%kernel.root_dir%]
medapp_private.filesystem:
class: Gaufrette\Filesystem
arguments: [@medapp_private.adapter]
medapp_private.adapter:
class: Sonata\MediaBundle\Filesystem\Local
arguments: [%private_filesystem_directory%,true]
无需为提供程序创建自定义文件系统或适配器,只需创建新服务并将目录传递给适配器,然后将适配器传递给文件系统,再将文件系统传递给自定义提供程序。这是在您不需要任何自定义功能的情况下。
我遇到了完全相同的问题,非常感谢上传解决方案。
从安全目录下载文件 - sonata 提供了一种方法,因此您甚至不需要此处概述的自定义提供程序:https://sonata-project.org/bundles/media/master/doc/reference/security.html
我的实现是这样的:
services:
sonata.media.provider.private:
class: Sonata\MediaBundle\Provider\FileProvider
tags:
- { name: sonata.media.provider }
arguments:
- 'sonata.media.provider.private'
- '@app.sonata.media.private.filesystem'
- '@sonata.media.cdn.server'
- '@sonata.media.generator.default'
- '@sonata.media.thumbnail.format'
app.sonata.media.private.filesystem:
class: Gaufrette\Filesystem
arguments: ['@app.sonata.media.private.adapter']
app.sonata.media.private.adapter:
class: Sonata\MediaBundle\Filesystem\Local
arguments:
- "%kernel.root_dir%/../doclib/uploads"
- true
具有明确定义的安全策略的上下文以控制谁可以访问文件。本例中的超级管理员:
sonata_media:
contexts:
privatefiles:
download:
strategy: sonata.media.security.superadmin_strategy
mode: http
providers:
- sonata.media.provider.private
在 twig 中,您可以获得可下载资源的链接,如下所示:
{{ path('sonata_media_download', { 'id':media|sonata_urlsafeid }) }}
sonata_media_download
映射 MediaController::downloadAction()
,它实现了您试图通过 getPrivateMedia()
.
我现在坚持的一点是为新提供者设置 allowed_extensions
等内容,因为 providers
部分不接受 private
作为名称,所以我假设这个需要在某处具体定义。
编辑: allowed_extensions
等可以通过自定义提供程序服务定义作为进一步的参数传递。