Php SonatamaDiabundle的公共和私有媒体上传到不同的文件夹(网络和私有)

Php SonatamaDiabundle的公共和私有媒体上传到不同的文件夹(网络和私有),php,symfony,sonata-admin,sonata-media-bundle,Php,Symfony,Sonata Admin,Sonata Media Bundle,我正在使用SonatamaDiabundle,到目前为止,我一直在Symfony的web文件夹中公开上传文件。以下是我的配置文件的一部分: contexts: default: # the default context is mandatory providers: - sonata.media.provider.dailymotion - sonata.media.provider.youtube

我正在使用SonatamaDiabundle,到目前为止,我一直在Symfony的
web
文件夹中公开上传文件。以下是我的配置文件的一部分:

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\u服务器路径:/uploads/media/

这将在
web/uploads/media/contextname/0001/01/***
中上载文件

由于位于公用文件夹中,所有人都可以看到这些文件。我知道我可以在
app/Resources/
中的某个地方更改此文件夹,但这将使我的所有文件都成为私有文件,我不希望这样。我所说的私人,是指他们应该由一名控制员以某种方式提供服务

我如何区分一些文件是公共的,而另一些文件是私有的?有没有办法让某个上下文上传的文件与另一个不同?还是其他方式

此外,将文件上载到app/Resources文件夹时,无法预览这些文件,因为它们的url变为非公共url,因为它不在web文件夹中,而web文件夹是Symfony仅有的公共文件。如何做到这一点


编辑:我已经完成了上传部分(检查下面的答案),但是检索部分有点麻烦。我仍在寻找一种方法。好的,我就快到了。我的文件正在上载到我想要的任何文件夹,但我在显示它们时遇到了问题

我们的想法是创建一个定制的提供者,它有自己的文件系统和适配器服务。问题是,我需要将文件上传到的文件夹传递给适配器服务。该适配器被传递到文件系统,然后文件系统被传递到提供者。SonatamaDiabundle的问题在于它不允许您修改适配器的目录,因此您必须创建自己的目录,并将其一直传递给您的提供商

服务:

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]
参数.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_媒体上下文中。我已将其添加到默认上下文中,例如:

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\0001\01
,文件将在其中上载

现在的问题是检索它们,因为它们没有公共链接,需要在控制器中检索。我在提供程序中创建了一个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提供了一种方法,因此您甚至不需要此处概述的自定义提供程序:

我对此的实现如下所示:

服务:
sonata.media.provider.private:
类别:Sonata\MediaBundle\Provider\FileProvider
标签:
-{名称:sonata.media.provider}
论据:
-'奏鸣曲.媒体.提供商.私人'
-“@app.sonata.media.private.filesystem”
-“@sonata.media.cdn.server”
-“@sonata.media.generator.default”
-“@sonata.media.缩略图.format”
app.sonata.media.private.filesystem:
类:gaufrete\Filesystem
参数:['@app.sonata.media.private.adapter']
app.sonata.media.private.adapter:
类别:Sonata\MediaBundle\Filesystem\Local
论据:
-%kernel.root\u dir%/../doclib/uploads
-真的
具有显式定义的安全策略的上下文,以控制谁可以访问文件。在这种情况下,超级管理员:

sonata_媒体:
上下文:
私人文件:
下载:
策略:sonata.media.security.superadmin\u策略
模式:http
供应商:
-索纳塔。媒体。提供商。私人
在twig中,您可以获得指向可下载资源的链接,如下所示:

{{path('sonata_media_download',{'id':media|sonata_urlsafeid}}}
sonata\u media\u download
maps
MediaController::downloadAction()
,它实现了您试图通过
getPrivateMedia()
实现的功能

我现在坚持的一点是为新提供者设置
允许的\u扩展
等内容,因为
提供者
部分不接受
私有
作为名称,所以我假设这需要在某个地方专门定义

编辑:
允许的\u扩展
等可以通过自定义提供程序服务定义作为进一步的参数传递