- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在努力解决一个问题,我需要 Sonata Media Bundle 将图片上传到不同的文件夹。我想要达到的是生成如下图片结构:如果图片的 ID 为 1234567,则原始图像将放入文件夹:“/web/uploads/1234/567/original”所有生成的缩略图/尺寸将类似于:“/web/uploads/1234/567/100x130”和“/web/uploads/1234/567/200x100”,具体取决于生成的尺寸。
在 Sonata Media Bundle 中是否可以生成此文件夹结构?如果可以,如何生成?
感谢您的回答。约瑟夫
最佳答案
我们为这个问题制定了一个“解决方法”:
基本上,我们所做的是创建自己的生成器、提供程序和调整器来满足我们的需求,然后将其注入(inject)回媒体包。生成器实现了 Generator 接口(interface),构造函数只有一个参数($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);
}
这将以首选方式为 ID 为“1234567”的图像创建子目录“/web/uploads/1234/567”。
我们的提供程序扩展了 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;
}
}
进行依赖项注入(inject)有点挑战,但结果如下:
服务:
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>:
我知道这不是最清晰的工作,但它确实完成了工作,目前还不错:)
关于symfony - 如何让 Sonata Media Bundle 在单独的文件夹中生成图片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27057300/
我想使用 Angular.js 转换从服务器获取的图像数据(用于 ionic 框架),我使用了这段代码: $http.post(link, { token: token,
我正在为我的应用制作一个登陆页面。如果它们在 iOS 设备上,我希望它只显示“App Store”图标,但在 Android 上隐藏它。如果它们在 Android 设备上,则只有“Play Store
如何在同一页面上多次显示同一张图片? function xdf(){ for (i=0;ihello world'); } } 此代码显示“hello world”10 次。我想要同样的东西,
您好,我有一个 1px 的 png 文件,我试图将其设置为两个水平相邻的 div 的背景图像。html 和 css 如下:- hi hello css是这样的 div { width: 50%
我的 PHP 项目安装了 Prestashop 1.4.9.0。当我添加一个新产品时,我上传了一个PNG格式的图片,但是当它在客户端显示时,图片是JPG格式的。 如何保留图片扩展名? 最佳答案 在后台
我用 http://www.regexper.com查看一个象形表示正则表达式很多。我想要一种理想的方法: 向站点发送正则表达式 打开显示该表达式的站点 例如,让我们使用正则表达式:"\\s*foo[
我不知道为什么在 MAC OS X (Mail 6.2) 的邮件客户端中图像显示如下: 和其他邮件客户端,如 gmail、outlook 或 private,图像是正确的,看起来像这样: PHP邮件程
我正在使用此处找到的示例。 Mozilla developers 我对这个例子很感兴趣。 function upload(postUrl, fieldName, filePath) { var f
我不知道为什么在 MAC OS X (Mail 6.2) 的邮件客户端中图像显示如下: 和其他邮件客户端,如 gmail、outlook 或 private,图像是正确的,看起来像这样: PHP邮件程
我的问题是如何根据用户在javafx中选择的复选框和/或单选按钮生成带有汽车图片设置的按钮? 我正在用汽车图片模拟汽车经销商网站。用户应该能够通过单击复选框和/或单选按钮选择来过滤显示的图片。 我首先
我正在开发Java客户端,它应该支持多种语言。为了翻译文本,我使用 Java ResourceBoundle,它工作正常。 现在问题出在图像上。客户端应加载大约 50 张图像,这些图像是棋盘游戏的特定
我对 jQuery 还很陌生,但我正在寻找一个简单的脚本,通过淡入和淡出的方式在标题中循环 3 或 4 个背景图像。它们是透明的 png,因此我尝试过的许多 slider 都不起作用。 有什么想法吗?
我有一个 HTML 文档,其中包含本地文件的图像,例如: ios - 物理主体大于它分配给的纹理(图片)
我的 Sprite “physicsBody ”属性之一出现问题。 我已经放置了physicsBody节点“barn ”,直接位于 non-physicsBody 之上节点“mound”没有任何问题。
我想剪切图片的特定部分并用它来将剪切的图像与存储在 HDD 中的另一个图像进行比较。问题是我不知道如何获取源图像的特定部分。我知道要裁剪的图像的位置 (X,Y)。 最佳答案 这将加载原始版本并创建
如何使用裁剪实用程序在 javascript 中实现图像 uploader 。你如何通过 AJAX 提交图像文件?解决方案是否跨域兼容? 最佳答案 要实现具有裁剪功能的图片上传小部件,您必须: 将图像
public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityRes
我想在我的 android 应用程序中显示一个国家的图片。国家必须按地区划分。因此,当用户单击特定区域时,应打开特定屏幕。区域也应该用线分隔,以便用户可以看到区域的开始/结束位置。 这是一个国家的例子
首先我想对这个问题表示歉意,因为我知道已经有很多人问过这个问题了。但我搜索的所有答案都没有解决我的问题。所以希望您考虑这个问题并帮助我解决这个问题。 所以基本上我正在尝试上传图像文件,当我提交它时,会
我几乎有了想要的数据...但需要帮助过滤它。 (图在底部) 下面的查询返回状态为 Member-id5 的所有记录,但我需要对其进行过滤。例如:如果我对等做了一个简单的查询。 (exp_channel
我是一名优秀的程序员,十分优秀!