Публичные и частные СМИ SonataMediaBundle загружены в разные папки (веб и частные)

Я использую SonataMediaBundle и до сих пор публично загружаю файлы в web папка Symfony. Вот часть моего файла конфигурации:

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/***,

Находясь в общей папке, эти файлы видны всем. Я знаю, что могу изменить эту папку где-нибудь в app/Resources/, но это сделает ВСЕ мои файлы приватными, чего я не хочу. Под частным я подразумеваю, что они должны обслуживаться контроллером, так или иначе.

Как разделить некоторые файлы как общедоступные, а другие как частные? Есть ли способ заставить определенный контекст загружать файлы иначе, чем другой? Или любым другим способом?

Кроме того, при загрузке файлов в папку app / Resources их нельзя просмотреть, так как их URL становится http://website.com/app/Resources/media/profile_pics/0001/01/85e05ab9685b1745af4e64ff98ef91eed6e4ccdf.jpeg который не является общедоступным, потому что он не находится в веб-папке, единственные общедоступные файлы, которые есть в Symfony. Как это может быть сделано?

РЕДАКТИРОВАТЬМне удалось выполнить загрузку (см. Ответ ниже), но получение части немного хлопотно. Я все еще ищу способ сделать это.

3

Решение

Хорошо, я почти там. Мои файлы загружаются в любую папку, которую я хочу, но у меня есть проблема с отображением их.

Идея заключается в создании собственного провайдера, который имеет свою собственную файловую систему и службы адаптера. Проблема заключалась в том, что мне нужно было передать службе адаптера папку, в которую я хочу, чтобы файлы были загружены. Этот адаптер передается в файловую систему, которая затем передается поставщику. Проблема с 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\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]

Нет необходимости создавать пользовательскую файловую систему или адаптер для поставщика, просто создайте новые службы и передайте каталог адаптеру, а затем передайте адаптер в файловую систему, а файловую систему — пользовательскому поставщику. Это если вам не нужны никакие пользовательские функции.

2

Другие решения

У меня была точно такая же проблема, поэтому большое спасибо за решение по загрузке.

Для загрузки файлов из защищенного каталога — 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

В ветке вы можете получить ссылки на загружаемый ресурс, например, так:

{{ path('sonata_media_download', { 'id':media|sonata_urlsafeid  }) }}

sonata_media_download карты MediaController::downloadAction(), который реализует функциональность, которую вы пытались достичь с getPrivateMedia(),

Я застрял в том, чтобы установить такие вещи, как allowed_extensions и т.д. для нового поставщика в качестве providers раздел не примет private как имя, поэтому я предполагаю, что это где-то определенно необходимо определить.

РЕДАКТИРОВАТЬ: allowed_extensions и т.д. могут быть переданы в качестве дополнительных аргументов через определение пользовательского сервиса провайдера.

0

По вопросам рекламы [email protected]