I just want to validate the extension of image that I upload in Sonata Admin (v3.28.0) with Sonata Media Bundle (v3.10.0) in Symfony (v2.8.32) application.
I've read all similar questions and Sonata documentations, but still don't have a success.
I tried to add constraints to config.yml
sonata_media:
providers:
image:
allowed_extensions:
- 'jpg'
- 'png'
I wonder that it doesn't work as is, because standard FileProvider (that is extended by ImageProvider) has extension check in validate method. But the method is not being called.
So I also tried to create custom provider:
services.yml:
sonata.media.provider.custom:
class: Application\Sonata\MediaBundle\Provider\CustomImageProvider
tags:
- { name: sonata.media.provider }
arguments:
- sonata.media.provider.custom
- #sonata.media.filesystem.local
- #sonata.media.cdn.server
- #sonata.media.generator.default
- #sonata.media.thumbnail.format
- ['jpg', 'png']
- ['image/pjpeg', 'image/jpeg', 'image/png', 'image/x-png']
- #sonata.media.adapter.image.imagick
- #sonata.media.metadata.proxy
calls:
- [ setTemplates, [{helper_view:SonataMediaBundle:Provider:view_image.html.twig,helper_thumbnail:SonataMediaBundle:Provider:thumbnail.html.twig}]]
Application\Sonata\MediaBundle\Provider\CustomImageProvider.php:
<?php
namespace Application\Sonata\MediaBundle\Provider;
use Sonata\CoreBundle\Validator\ErrorElement;
use Sonata\MediaBundle\Model\MediaInterface;
use Sonata\MediaBundle\Provider\ImageProvider;
class CustomImageProvider extends ImageProvider
{
public function validate(ErrorElement $errorElement, MediaInterface $media)
{
throw new \Exception();
}
}
config.yml:
sonata_media:
contexts:
image:
providers:
- sonata.media.provider.custom
formats:
small: { width: 100 , quality: 70}
big: { width: 500 , quality: 70}
But the validate method is still not being called.
So when I try to load GIF image I get an error:
Length of either side cannot be 0 or negative, current size is x
Do I miss something?
UPDATE
Simple validation can be added right in SomeEntityAdmin class like this:
public function validate(ErrorElement $errorElement, $object)
{
/** #var Media $image */
$image = $object->getImage();
if (!in_array($video->getContentType(), ['image/pjpeg', 'image/jpeg', 'image/png', 'image/x-png'])) {
$errorElement
->with('image')
->addViolation('Invalid file type')
->end()
;
};
}
But it's not a good solution if you want to validate a batch of uploaded images.
Related
I have the bundle installed and configured with Sonata Admin Bundle, when I try to remove an Image, the image is properly deleted from the folder but not the thumbnail stored in media/cache.
this is my liip_imagine yml:
liip_imagine:
loaders:
loader_s3_thumbnail:
stream:
wrapper: gaufrette://questions_image_fs/
filter_sets:
question_thumb:
cache: default
data_loader: loader_s3_thumbnail
# list of transformations to apply (the "filters")
filters:
thumbnail: { size: [120, 120], mode: outbound }
provider_thumb:
cache: default
data_loader: loader_s3_thumbnail
# list of transformations to apply (the "filters")
filters:
thumbnail: { size: [200, 200], mode: inset }
Any Idea why or how to delete this thumbnails?
Workmate managed to solve it using Liip cachemanager. Here is the code:
Service:
question.admin_bundle.event_listener.delete_thumbnails:
class: QuestionAdminBundle\EventListener\DeleteThumbnails
arguments: [ "#liip_imagine.cache.manager" ]
tags:
- { name: kernel.event_listener, event: vich_uploader.pre_remove, method: postRemove}
Php:
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
[...]
public function __construct(CacheManager $cacheManager)
{
Add a comment to this line
$this->cacheManager = $cacheManager;
}
[...]
public function postRemove(Event $event)
{
$image = $event->getObject();
if ($image instanceof Image){
$this->cacheManager->remove($image->getName());
}
}
I'm using Symfony3 with the KnpGaufretteBundle to connect to an Amazon S3 bucket with the AWS S3 method outlined on their Github Readme
aws_s3_adapter:
key: "%aws_key%"
secret_key: "%aws_secret%"
region: "%aws_region%"
knp_gaufrette:
adapters:
images:
aws_s3:
service_id: 'aws_s3_adapter.client'
bucket_name: '%aws_bucket%'
options:
directory: 'images'
filesystems:
images:
adapter: images
alias: images_fs
I also have a service defined that I want to use to manage this filesystem (and others) with.
Definition:
services:
test.image_manager:
class: TestBundle\Filesystem\FileManager
arguments:
filesystem: "#images_fs"
filesystem_name: "images"
mimetypes: ["image/jpeg", "image/png", "image/gif"]
Class:
<?php
namespace TestBundle\Filesystem;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Gaufrette\Filesystem;
use Gaufrette\StreamWrapper;
class FileManager
{
private $allowedMimeTypes;
private $filesystem;
private $filsystem_name;
public function __construct(Filesystem $filesystem, $filesystem_name, $mimetypes = array())
{
$this->filesystem = $filesystem;
$this->filesystem_name = $filesystem_name;
$this->allowedMimeTypes = $mimetypes;
}
public function upload(UploadedFile $file, $filename)
{
// Check if the file's mime type is in the list of allowed mime types.
if (!in_array($file->getClientMimeType(), $this->allowedMimeTypes)) {
throw new \InvalidArgumentException(sprintf('Files of type %s are not allowed.', $file->getClientMimeType()));
}
$adapter = $this->filesystem->getAdapter();
$adapter->setMetadata($filename, array('contentType' => $file->getClientMimeType()));
return $adapter->write($filename, file_get_contents($file->getPathname()));
}
public function fetch( $filename )
{
if( ! $this->filesystem->has( $filename ) )
{
return false;
}
/* -- PROBLEM -- */
StreamWrapper::register();
return new BinaryFileResponse( "gaufrette://{$this->filesystem_name}/{$filename}" );
/* -- PROBLEM -- */
}
public function delete( $filename )
{
if( ! $this->filesystem->has( $filename ) )
{
return false;
}
return $this->filesystem->delete( $filename );
}
}
I'm able to upload successfully to the bucket using the upload function, telling me that the filesystem exists and is working properly.
I am not, however, able to use the Gaufrette\StreamWrapper to serve the file using a BinaryFileResponse as it says I should do. Instead it is giving me the error that I put in the title: There is no filesystem defined for the "images" domain.
The filesystem definitely exists, as I'm using it to upload the images. Any clues as to what the problem might be that's preventing me from using that filesystem would be very helpful. The Gaufrette documentation is really sparse online so far as I've found, but I'm going to keep digging.
Looking at MainConfiguration.php showed that there's a steam_wrapper option in the configuration for the bundle. I added this into my config.yml under where the filesystems are defined like so:
knp_gaufrette:
adapters:
images:
aws_s3:
service_id: 'aws_s3_adapter.client'
bucket_name: '%aws_bucket%'
options:
directory: 'images'
.
.
.
filesystems:
images:
adapter: images
alias: images_fs
.
.
.
stream_wrapper:
filesystems: [ images, ... ]
and the above code now works.
If I don't validate what I am uploading things work fine but the moment I add validation to the image field I get an error of
Serialization of 'Symfony\Component\HttpFoundation\File\UploadedFile' is not allowed
The only thing at the moment I have inside my validation.yml is as following
AppBundle\Entity\User:
properties:
firstName:
- NotBlank: {message: "user.firstname.not_blank"}
lastName:
- NotBlank: { message: "user.lastname.not_blank" }
profileImage:
- Image:
Inside my Entity
use Symfony\Component\HttpFoundation\File\File;
public function setProfileImage(File $profileImage = null)
{
$this->profileImage = $profileImage;
return $this;
}
What am I missing here? This used to work fine in Symfony 2.7
I'm having the same problem symfony2 is describing here
This comes in handy when you have a bundle but don't want to manually
add the routes for the bundle to app/config/routing.yml. This may be
especially important when you want to make the bundle reusable
TLDR; im trying to implement a custom Route Loader using this part of the symfony2 documentation
http://symfony.com/doc/current/cookbook/routing/custom_route_loader.html#more-advanced-loaders
However it doesn't seem to be working, the route cannot be found;
This is what I've tried so far:
The loader:
<?php
//namespace Acme\DemoBundle\Routing;
namespace Gabriel\AdminPanelBundle\Routing;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Routing\RouteCollection;
class AdvancedLoader extends Loader
{
public function load($resource, $type = null)
{
$collection = new RouteCollection();
$resource = '#GabrielAdminPanelBundle/Resources/config/routing.yml';
$type = 'yaml';
$importedRoutes = $this->import($resource, $type);
$collection->addCollection($importedRoutes);
return $collection;
}
public function supports($resource, $type = null)
{
return $type === 'advanced_extra';
}
}
here is my routing.yml
located in: src/Gabriel/AdminPanelBundle/Resources/config/routing.yml
the routing.yml
gabriel_admin_panel:
resource: "#GabrielAdminPanelBundle/Controller/"
type: annotation
prefix: /superuser
The Routes of the bundle can't be found unless I put the Routes back in the main app/config/routing.yml file, how to fix this?
Edit:
FileLoaderImportCircularReferenceException: Circular reference
detected in "/app/config/routing_dev.yml"
("/app/config/routing_dev.yml" > "/app/config/routing.yml" > "." >
"#GabrielAdminPanelBundle/Controller/" >
"/app/config/routing_dev.yml").
You must also configure service
# src/Gabriel/AdminPanelBundle/Resources/config/services.yml
your_bundle.routing_loader:
class: Gabriel\AdminPanelBundle\Routing\AdvancedLoader
tags:
- { name: routing.loader }
And routing file
# app/config/routing.yml
YourBundle_extra:
resource: .
type: advanced_extra
I'm trying to upload one or more files using OneupUploaderBundle but I can not get it to work since files aren't uploaded and nothing is persisted to DB. I'll explain what I've done til now:
config.yml:
oneup_uploader:
mappings:
recaudos:
frontend: blueimp
storage:
service: ~
type: filesystem
filesystem: ~
directory: %kernel.root_dir%/../web/uploads/recaudos
stream_wrapper: ~
sync_buffer_size: 100K
allowed_mimetypes: [application/msword,image/jpeg,image/pjpeg,image/png,application/pdf,application/vnd.oasis.opendocument.text]
#disallowed_mimetypes: []
error_handler: oneup_uploader.error_handler.noop
# Set max_size to -1 for gracefully downgrade this number to the systems max upload size.
#max_size: 9223372036854775807
use_orphanage: true
enable_progress: true
enable_cancelation: true
namer: oneup_uploader.namer.uniqid
At Twig template only this:
<input id="fileUpload3" class="fileUpload" type="file" name="fileUpload3[]" data-url="{{ oneup_uploader_endpoint('recaudos') }}" multiple />
$(document).ready(function(){
$('fileUpload3').fileupload();
});
And latest this is the Listener for onUpload event:
namespace AppBundle\EventListener;
use Oneup\UploaderBundle\Event\PostPersistEvent;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity;
class UploadListener
{
protected $doctrine;
public function __construct($doctrine)
{
$this->doctrine = $doctrine;
}
public function onUpload(PostPersistEvent $event, Request $request)
{
$session = $request->getSession();
$em = $this->doctrine->getManager();
$request = $event->getRequest();
$tempfile = $event->getFile();
$productoSolicitud = $em->getRepository('SolicitudProducto')->find($session->get('productoSolicitudId'));
$recaudosTramiteProductoSolicitud = new Entity\RecaudosTramitesProductoSolicitud();
$recaudosTramiteProductoSolicitud->setProductoSolicitud($productoSolicitud);
$filenamePart = explode("--", $tempfile->getName());
$pathinfo = pathinfo($tempfile->getName());
$recaudosTramiteProductoSolicitud->setArchivo($pathinfo['filename']);
$em->persist($recaudosTramiteProductoSolicitud);
$em->flush();
}
}
And of course I have service defined also:
appbundle.upload_listener:
class: "AppBundle\EventListener\UploadListener"
arguments: [#doctrine]
tags:
- { name: 'kernel.event_listener', event: "oneup_uploader.post_persist", method: "onUpload" }
Did I miss something? Why file are not uploaded and data is not persisted? As you may see in the attached image there is a post request to _uploader/recaudos/upload, any advice?
I just checked my own OneupUploader implementation:
Rename your function "onUpload" to "onPostUpload" and change your service configuration to this:
appbundle.upload_listener:
class: "AppBundle\EventListener\UploadListener"
arguments: [#doctrine]
tags:
- { name: 'kernel.event_listener', event: oneup_uploader.post_upload, method: onPostUpload }
Should work, works for me.
If you need your original file name you also need an onUpload Method and this:
tags:
# - {...
- { name: kernel.event_listener, event: oneup_uploader.pre_upload, method: onUpload }
Regarding your comment:
//UploadListener
class UploadListener
{
protected $originalName;
public function onUpload(PreUploadEvent $event)
{
$file = $event->getFile();
$this->originalName = $file->getClientOriginalName();
}
public function onPostUpload(PostUploadEvent $event)
{
$fileEntity = new YourFileEntity();
$fileEntity->setYourOriginalNameProperty($this->originalName);
//...
}
}