簡體   English   中英

如何獲取Sonata Media Bundle在單獨的文件夾中生成圖片

[英]How to get Sonata Media Bundle to generate pictures in separate folders

我遇到一個問題,我需要Sonata Media Bundle將圖片上傳到不同的文件夾。 我要達到的目的是生成如下的圖片結構:如果圖片的ID為1234567,則原始圖片將放入文件夾中:“ / web / uploads / 1234/567 / original',所有生成的圖片縮略圖/大小將取決於生成的大小,例如:“ / web / uploads / 1234/567 / 100x130”和“ / web / uploads / 1234/567 / 200x100”。

可以在Sonata Media Bundle中生成此文件夾結構嗎?如果可以,怎么辦?

感謝您的回答。 約瑟夫·

我們針對此問題制定了“解決方案”:

基本上,我們要做的就是創建自己的Generator,Provider和Resizer來滿足我們的需求,然后將其注入Media Bundle。 生成器實現了Generator接口,構造函數只有一個參數($ this-> firstLevel = 1000;)。 比:

public function generatePath(MediaInterface $media)
{
    $rep_first_level = (int) ($media->getId() / $this->firstLevel);
    $rep_second_level = (int) ($media->getId() % $this->firstLevel);

    return sprintf('%s/%04s/%03s', $media->getContext(), $rep_first_level, $rep_second_level);
}

這將以首選方式“ / web / uploads / 1234/567”為ID為“ 1234567”的圖像創建子目錄。

我們的提供程序擴展了ImageProvider,並且只有1個實例:

protected function generateReferenceName(MediaInterface $media)
{
    $metadata = $media->getProviderMetadata();
    $fileName = $metadata['filename'];
    $temp = explode('.', $fileName);
    $name = $temp[0];
    return '/origos/' . $name . '.' . $media->getBinaryContent()->getExtension();
}

我們的Resizer類將擴展squareResizer。 對其進行了更改,使其能夠通過裁剪圖像來生成大小正確的圖片(縮略圖)(也為100x100和190x100)。 為此,我們創建了一個實現ResizerInterface的新調整器:

<?php

namespace Sita\<YourBundle>\Resizer;

use Imagine\Image\ImagineInterface;
use Imagine\Image\Box;
use Imagine\Image\Point;
use Gaufrette\File;
use Sonata\MediaBundle\Model\MediaInterface;
use Sonata\MediaBundle\Metadata\MetadataBuilderInterface;
use Sonata\MediaBundle\Resizer\ResizerInterface;

class <YourResizer> implements ResizerInterface
{
    /**
     * ImagineInterface
     */
    protected $adapter;

    /**
     * string
     */
    protected $mode;

    /**
     * @param ImagineInterface $adapter
     * @param string $mode
     * @param MetadataBuilderInterface $metadata
     */
    public function __construct(ImagineInterface $adapter, $mode, MetadataBuilderInterface $metadata)
    {
        $this->adapter = $adapter;
        $this->mode    = $mode;
        $this->metadata = $metadata;
    }

    /**
     * {@inheritdoc}
     */
    public function resize(MediaInterface $media, File $in, File $out, $format, array $settings)
    {
        if (!isset($settings['width'])) {
            throw new \RuntimeException(sprintf('Width parameter is missing in context "%s" for provider "%s"', $media->getContext(), $media->getProviderName()));
        }

        $image = $this->adapter->load($in->getContent());
        $size  = $media->getBox();

        if (null != $settings['height']) {
            $ratioWidth = $size->getWidth() / $settings['width'];
            $ratioHeight = $size->getHeight() / $settings['height'];
            $ratio = $ratioHeight > $ratioWidth ? $ratioWidth : $ratioHeight;

            $point = new Point(($size->getWidth() - $settings['width'] * $ratio) / 2, ($size->getHeight() - $settings['height'] * $ratio) / 2);

            $image->crop($point, new Box($settings['width'] * $ratio, $settings['height'] * $ratio));
            $size = $image->getSize();
        }

        $settings['height'] = (int) ($settings['width'] * $size->getHeight() / $size->getWidth());

        if ($settings['height'] < $size->getHeight() && $settings['width'] < $size->getWidth()) {
            $content = $image
                ->thumbnail(new Box($settings['width'], $settings['height']), $this->mode)
                ->get($format, array('quality' => $settings['quality']));
        } else {
            $content = $image->get($format, array('quality' => $settings['quality']));
        }

        $out->setContent($content, $this->metadata->get($media, $out->getName()));
    }

    /**
     * {@inheritdoc}
     */
    public function getBox(MediaInterface $media, array $settings)
    {
        $size = $media->getBox();

        if (null != $settings['height']) {

            if ($size->getHeight() > $size->getWidth()) {
                $higher = $size->getHeight();
                $lower  = $size->getWidth();
            } else {
                $higher = $size->getWidth();
                $lower  = $size->getHeight();
            }

            if ($higher - $lower > 0) {
                return new Box($lower, $lower);
            }
        }

        $settings['height'] = (int) ($settings['width'] * $size->getHeight() / $size->getWidth());

        if ($settings['height'] < $size->getHeight() && $settings['width'] < $size->getWidth()) {
            return new Box($settings['width'], $settings['height']);
        }

        return $size;
    }
}

進行依賴注入有點挑戰,但是結果如下:

服務:

    parameters:
    <yourBundle>.generator.<project>_generator.class: Sita\<yourBundle>\Generator\<project>Generator
    <yourBundle>.resizer.<project>_resizer.class: Sita\<yourBundle>\Resizer\<project>Resizer
    <yourBundle>.thumbnail.<project>_thumbnail.class: Sita\<yourBundle>\Thumbnail\<project>Thumbnail
    <yourBundle>.provider.<project>_provider.class: Sita\<yourBundle>\Provider\<project>Provider
services:
    <yourBundle>.generator.<project>_generator:
        class: %<yourBundle>.generator.<project>_generator.class%
        arguments:
            - ~

    <yourBundle>.resizer.<project>_resizer:
        class: %<yourBundle>.resizer.<project>_resizer.class%
        arguments:
            - @sonata.media.adapter.image.gd
            - %sonata.media.resizer.square.adapter.mode%
            - @sonata.media.metadata.proxy

    <yourBundle>.thumbnail.<project>_thumbnail:
        class: %<yourBundle>.thumbnail.<project>_thumbnail.class%
        arguments:
            - %sonata.media.thumbnail.format.default%

    <yourBundle>.provider.<project>:
        class: %<yourBundle>.provider.<project>_provider.class%
        arguments:
            - <yourBundle>.provider.<project>
            - ~
            - ~
            - ~
            - @<yourBundle>.thumbnail.<project>_thumbnail
            - ~
            - ~
            - ~
            - @sonata.media.metadata.proxy
        calls:
            - [setResizer, ["@<yourBundle>.resizer.<project>_resizer"]]
        tags:
            - { name: sonata.media.provider }

組態:

<?php

namespace <yourBundle>\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * This is the class that validates and merges configuration from your app/config files
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
 */
class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritdoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('<yourBundle>');

        $rootNode
            ->children()
                ->arrayNode('providers')
                    ->addDefaultsIfNotSet()
                    ->children()
                        ->arrayNode('<project>')
                            ->addDefaultsIfNotSet()
                            ->children()
                                ->scalarNode('service')->defaultValue('<yourBundle>.provider.<project>')->end()
                                ->scalarNode('resizer')->defaultValue('<yourBundle>.resizer.<project>_resizer')->end()
                                ->scalarNode('filesystem')->defaultValue('sonata.media.filesystem.local')->end()
                                ->scalarNode('cdn')->defaultValue('sonata.media.cdn.server')->end()
                                ->scalarNode('generator')->defaultValue('<yourBundle>.generator.<project>_generator')->end()
                                ->scalarNode('thumbnail')->defaultValue('<yourBundle>.thumbnail.<project>_thumbnail')->end()
                                ->scalarNode('adapter')->defaultValue('sonata.media.adapter.image.gd')->end()
                                ->arrayNode('allowed_extensions')
                                    ->prototype('scalar')->end()
                                    ->defaultValue(array('jpg', 'png', 'jpeg'))
                                ->end()
                                ->arrayNode('allowed_mime_types')
                                    ->prototype('scalar')->end()
                                    ->defaultValue(array(
                                        'image/pjpeg',
                                        'image/jpeg',
                                        'image/png',
                                        'image/x-png',
                                    ))
                                ->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end();

        return $treeBuilder;
    }
}

和擴展名:

<?php

namespace <yourBundle>\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

/**
 * This is the class that loads and manages your bundle configuration
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
 */
class <yourBundle>Extension extends Extension
{
    /**
     * {@inheritdoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.yml');

        $container->getDefinition('<yourBundle>.provider.<project>')
            ->replaceArgument(1, new Reference($config['providers']['<project>']['filesystem']))
            ->replaceArgument(2, new Reference($config['providers']['<project>']['cdn']))
            ->replaceArgument(3, new Reference($config['providers']['<project>']['generator']))
            ->replaceArgument(4, new Reference($config['providers']['<project>']['thumbnail']))
            ->replaceArgument(5, array_map('strtolower', $config['providers']['<project>']['allowed_extensions']))
            ->replaceArgument(6, $config['providers']['<project>']['allowed_mime_types'])
            ->replaceArgument(7, new Reference($config['providers']['<project>']['adapter']))
        ;

    }
}

最后是symfony配置文件中的config.yml:

sonata_media:
    # if you don't use default namespace configuration
    #class:
    #    media: MyVendor\MediaBundle\Entity\Media
    #    gallery: MyVendor\MediaBundle\Entity\Gallery
    #    gallery_has_media: MyVendor\MediaBundle\Entity\GalleryHasMedia
    default_context: default
    db_driver: doctrine_orm # or doctrine_mongodb, doctrine_phpcr
    contexts:
        default:  # the default context is mandatory
            providers:
                - <yourBundle>.provider.<project>

            formats:
                small: { width: 100 , quality: 70}
                big:   { width: 500 , quality: 70}
                100x100: { width: 100 , height: 100 , quality: 100 }
                126x190: { width: 126 , height: 190 , quality: 100 }
                190x126: { width: 190 , height: 126 , quality: 100 }
                190x56: { width: 190 , height: 56 , quality: 100 }

    cdn:
        server:
            path: /uploads/media # http://media.sonata-project.org/

    filesystem:
        local:
            directory:  %kernel.root_dir%/../web/uploads/media
            create:     true

<yourBundle>:

我知道這不是最清晰的工作,但它確實可以完成工作,暫時還不錯:)

 //config.yml 
 sonata_media:
    contexts:
        default:  # the default context is mandatory
            providers:
                - sonata.media.provider.image

            formats:
                small: { width: 100 , quality: 70}
                big:   { width: 500 , quality: 70}

 //Controller action:
 $media = //$entity->getMedia(); Media entity
 $mediaProvider = $this->get('sonata.media.provider.image'); 
 $format = $mediaProvider->getFormatName($media, 'big');
 $imgPath = $mediaProvider->generatePublicUrl($media, $format);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM