afe_collection_upload
Collection Upload adds twitter-boostrap GUI wrapper for a collection
of objects associated with files. Objects hold the file in file
FileType
field and must implement Avocode\FormExtensionsBundle\Form\Model\UploadCollectionFileInterface
.
- Drag & drop support
- Copy & paste support
- Multiple file selection
- Display selected files in a table
- Display selected images thumbnails
- Display selected files size (browsers with HTML5 File API support only)
- Display uploaded files in a table
- Display uploaded images thumbnails
- Sort uploaded files
- Edit additional object fields (like name, description, etc)
- Asynchronous upload
To use this form type you must choose one of the following methods:
Install VichUploaderBundle and configure it's mappings:
vich_uploader:
db_driver: orm
gaufrette: false
storage: vich_uploader.storage.file_system
mappings:
gallery_image:
uri_prefix: /gallery/image
upload_destination: %kernel.root_dir%/../web/gallery/image
namer: vich_uploader.namer_uniqid
inject_on_load: true
delete_on_remove: true
delete_on_update: true
Add Vich mappings to your entity, implement UploadCollectionFileInterface
, and
add additional fields.
Note: This example also shows how to use [Gedmo Sortable] (https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/sortable.md) for sortable behaviour on Doctrine ORM. If you're useing diffrent ORM just remove Gedmo annotations. The sortable behaviour of this form type simply updates a hidden field with a
0-indexed
position key.
<?php
// Acme\DemoBundle\Entity\GalleryImage.php
namespace Acme\DemoBundle\Entity;
use Avocode\FormExtensionsBundle\Form\Model\UploadCollectionFileInterface;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Entity(repositoryClass="Gedmo\Sortable\Entity\Repository\SortableRepository")
* @Vich\Uploadable
*/
class GalleryImage implements UploadCollectionFileInterface
{
/**
* @Vich\UploadableField(mapping="gallery_image", fileNameProperty="path")
*/
protected $file;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
protected $path;
/**
* (Optional) nameable field
*
* @ORM\Column(type="string", length=255, nullable=true)
*/
protected $name;
/**
* (Optional) additional editable field
*
* @ORM\Column(type="string", length=255, nullable=true)
*/
protected $description;
/**
* (Optional) sortable group
*
* @Gedmo\SortableGroup
* @ORM\ManyToOne(targetEntity="Album", inversedBy="images")
* @ORM\JoinColumn(name="album_id", referencedColumnName="id")
*/
protected $album;
/**
* (Optional) sortable position
*
* @Gedmo\SortablePosition
* @ORM\Column(name="position", type="integer")
*/
protected $position;
}
Note: In this example we use Doctrine ORM, replace it's mappings with your ORM.
To use VichUploaderBundle you have to configure the upload_manager
option. Read more in
cookbook entry [How to use upload manager with this bundle?]
(https://github.com/avocode/FormExtensions/blob/master/Resources/doc/cookbook/upload-manager.md)
Follow symfony's cookbook on [How to handle File Uploads with Doctrine] (http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html) and apply following changes to your entity:
<?php
// Acme\DemoBundle\Entity\GalleryImage.php
namespace Acme\DemoBundle\Entity;
use Avocode\FormExtensionsBundle\Form\Model\UploadCollectionFileInterface;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @ORM\Entity(repositoryClass="Gedmo\Sortable\Entity\Repository\SortableRepository")
*/
class GalleryImage implements UploadCollectionFileInterface
{
protected $file;
// other fields like path, name, description, album, position
// stay the same as in "Useing VichUploader" example
public function getFile()
{
// inject file into property (if uploaded)
if ($this->getAbsolutePath()) {
return new \Symfony\Component\HttpFoundation\File\File(
$this->getAbsolutePath()
);
}
return null;
}
// see note below
public function getFileWebPath()
{
return $this->getWebPath();
}
}
Note: The second method's name must be
get FIELD WebPath
, in this example our field name isfile
so method name isgetFileWebPath
.
Admingenerator basic configuration:
images:
label: Images
dbType: collection
formType: afe_collection_upload
addFormOptions:
primary_key: id
nameable: true
nameable_field: name
sortable: true
sortable_field: position
editable: [ description ]
#
### you can create your own form type
# type: \Acme\DemoBundle\Form\MyFormType
#
### or use admin:generate-admin command and use the admingenerated form type
# type: \Acme\DemoBundle\Form\Type\Image\EditType
#
maxNumberOfFiles: 5
maxFileSize: 500000
minFileSize: 1000
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
loadImageFileTypes: /^image\/(gif|jpe?g|png)$/i
loadImageMaxFileSize: 250000
previewMaxWidth: 100
previewMaxHeight: 100
previewAsCanvas: true
prependFiles: false
allow_add: true
allow_delete: true
error_bubbling: false
options:
data_class: Acme\DemoBundle\Entity\GalleryImage
Your object must implement UploadCollectionFileInterface
functions:
public function getSize()
public function setParent($parent)
public function setFile(\Symfony\Component\HttpFoundation\File\File $file)
public function getFile()
public function getPreview()
<?php
// ...
public function setFile(\Symfony\Component\HttpFoundation\File\File $file) {
$this->file = $file;
return $this;
}
public function getFile() {
return $this->file;
}
public function getSize() {
return $this->file->getFileInfo()->getSize();
}
public function setParent($parent) {
$this->setAlbum($parent);
}
public function getPreview() {
return (preg_match('/image\/.*/i', $this->file->getMimeType()));
}
The only diffrence is in getFile
method which must inject the file and
other methods cannot direcly access the file
property, becouse it would be null
.
<?php
// ...
public function getFile() {
// inject file into property (if uploaded)
if ($this->getAbsolutePath()) {
return new \Symfony\Component\HttpFoundation\File\File(
$this->getAbsolutePath()
);
}
return null;
}
public function getSize() {
return $this->getFile()->getFileInfo()->getSize();
}
public function getPreview() {
return (preg_match('/image\/.*/i', $this->getFile()->getMimeType()));
}
type: string
default: id
File related object must have a unique primary key field.
type: boolean
default: true
If true, enables nameable behaviour.
type: string
default: name
Uses this field to store name.
type: boolean
default: false
If true, enables sortable behaviour.
type: string
default: position
Uses this field to store position.
type: array
default: []
List of additional fields to be rendered.
Note: Remember to add your fields to your form type!
type: integer
default: undefined
This option limits the number of files that are allowed to be uploaded using this widget. By default, unlimited file uploads are allowed.
Note: The maxNumberOfFiles setting acts like an internal counter and will adjust automatically when files are added or removed. That is, if you set it to 2 and add one file, it will be decreased to 1. If you remove one file from list, it will be increased again.
type: integer
default: undefined
The maximum allowed file size in bytes, by default unlimited.
Note: This option has only an effect for browsers supporting the File API.
type: integer
default: undefined
The minimum allowed file size, by default undefined (can be 0 bytes).
Note: This option has only an effect for browsers supporting the File API.
type: Regular Expression
default: undefined
If defined the regular expression for allowed file types is matched against either file type or file name as only browsers with support for the File API report the file type.
type: Regular Expression
default: /^image\/(gif|jpe?g|png)$/i
The regular expression to define for which files a preview image is shown, matched against the file type.
Note: Preview images are only displayed for browsers supporting the URL or webkitURL APIs or the readAsDataURL method of the FileReader interface.
type: integer
default: 5000000
The maximum file size for preview images in bytes.
type: integer
default: 80
The maximum width of the preview images.
type: integer
default: 80
The maximum height of the preview images.
type: boolean
default: true
If true and supported by the browser, selected images will be previewed as canvas elements, otherwise img elements will be used.
type: string
default: null
If set, given filter will be applied on uploaded file to generate a thumbnail.
Note: Requires instaling and configureing image manipulator. See [How to use image manipulator with this bundle?] (https://github.com/avocode/FormExtensions/blob/master/Resources/doc/cookbook/image-manipulator.md) cookbook entry.
type: boolean
default: false
By default, files are appended to the files container. Set this option to true, to prepend files instead.
Important: These options are just for User Interface and cannot be considered safe (javascript is client-side). Always validate form input data server-side!
type: boolean
default: false
Does added files must be automatically uploaded? See [use CollectionUploadType in asynchronous mode] documentation.
type: string
default: null
Route name used for asynchronous upload. See [use CollectionUploadType in asynchronous mode] documentation.
type: array
default: array()
Parameters for route used for asynchronous upload. See use CollectionUploadType in asynchronous mode documentation.
You can use the collection upload type in two different modes: 1- files are uploaded on form submission (synchronous mode) 2- files are uploaded before form is submit.
These two modes have their own advantages and drawbacks. User experience may also change a little:
-
Synchronous mode:
-
Select only files from the same folder
-
No unnecesary disk usage
-
-
Asynchronous mode:
-
Select files from different folders
-
Get "progress bar" visual
-
Start buttons available
-
May require a cron to clean temporary upload directory
-
See use CollectionUploadType in asynchronous mode documentation for more informations.
Special thanks to Sebastian Tschan for
jQuery-File-Upload
licensed under [MIT License]
(https://github.com/blueimp/jQuery-File-Upload#license).