diff --git a/Documentation/ApiOverview/Fal/UsingFal/ExamplesFileFolder.rst b/Documentation/ApiOverview/Fal/UsingFal/ExamplesFileFolder.rst index 59a284ab6a..d438ef726a 100644 --- a/Documentation/ApiOverview/Fal/UsingFal/ExamplesFileFolder.rst +++ b/Documentation/ApiOverview/Fal/UsingFal/ExamplesFileFolder.rst @@ -180,8 +180,8 @@ The simplest solution is to create a database entry into table using the :ref:`database connection ` class or the :ref:`query builder ` provided by TYPO3. -A cleaner solution using :ref:`Extbase ` requires far more work. An -example can be found here: https://github.com/helhum/upload_example +See :ref:`Extbase file upload ` for details on how +to achieve this using :ref:`Extbase `. .. _fal-using-fal-examples-file-folder-get-references: diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/FileUpload.rst b/Documentation/ExtensionArchitecture/Extbase/Reference/FileUpload.rst new file mode 100644 index 0000000000..e8bc401d41 --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/FileUpload.rst @@ -0,0 +1,489 @@ +.. include:: /Includes.rst.txt + +.. index:: Extbase, FileUpload + +.. _extbase_fileupload: + +=========== +File upload +=========== + +Implementing file uploads / attachments to Extbase Domain Models +has always been a bit of a challenge. + +While it is easy to access an existing file reference in a Domain Model, +writing new files to the :ref:`FAL (File Access Layer) ` +takes more effort. + +.. _extbase_fileupload_accessing: + +Accessing a file reference in an Extbase Domain Model +----------------------------------------------------- + +You need two components for the structural information: The Domain +Model definition and the TCA entry. + +.. literalinclude:: _FileUpload/_Blog.php + :caption: EXT:my_extension/Classes/Domain/Model/Blog.php + +.. literalinclude:: _FileUpload/_tx_myextension_domain_model_blog.php + :caption: EXT:my_extension/Configuration/TCA/tx_myextension_domain_model_blog.php + +Once this is set up, you can create/edit records through the TYPO3 +backend, attach a single or multiple files in it. Then using a normal +controller and fluid template, you can display an image: + +.. literalinclude:: _FileUpload/_BlogController.php + :caption: EXT:my_extension/Classes/Controller/BlogController.php + +.. literalinclude:: _FileUpload/_Show.html + :caption: EXT:my_extension/Resources/Private/Templates/Blog/Show.html + +On the PHP-side within controllers, you can use the usual +:php:`$blogItem->getSingleFile()` and :php:`$blogItem->getMultipleFilers()` +Extbase getters to retrieve the FileReference object. + +.. _extbase_fileupload_writing: + +Writing FileReference entries +----------------------------- + +.. _extbase_fileupload_writing-manual: + +Manual handling +............... + +With TYPO3 versions below v13, attaching files to an Extbase Domain Model +was only possible by either: + +* Manually evaluate the :php:`$_FILES` data, process and validate the data, + use raw QueryBuilder write actions on :sql:`sys_file` and :sql:`sys_file_reference` + to persist the files quickly, or use at least some API methods: + + .. literalinclude:: _FileUpload/_ApiUpload.php + :caption: EXT:my_extension/Classes/Controller/BlogController.php, excerpt + + Instead of raw access to :php:`$_FILES`, starting with TYPO3 v12 the recommendation + is to utilize the :ref:`UploadedFile objects instead of $_FILES `. + In that case, validators can be used for custom UploadedFile objects to specify restrictions + on file types, file sizes and image dimensions. + +* Use (or better: adapt) a more complex implementation by using Extbase TypeConverters, + as provided by `Helmut Hummel's EXT:upload_example `__. + This extension is no longer maintained and will not work without larger adaptation for + TYPO3 v12 compatibility. + +.. _extbase_fileupload_writing-attributes: + +Automatic handling based on PHP Attributes +.......................................... + +Starting with TYPO3 v13 it is finally possible to streamline this with commonly +know Extbase logic, as implemented via +:ref:`Feature: #103511 - Introduce Extbase file upload and deletion handling `. + +An example implementation of this can be found on +`Torben Hansen's EXT:extbase-upload `__ +repository. + +The general idea is to use PHP attributes within the Extbase Model, and for the upload +use a custom ViewHelper: + +.. literalinclude:: _FileUpload/_BlogEnhanced.php + :caption: EXT:my_extension/Classes/Domain/Model/Blog.php, using FileUpload attributes + +.. literalinclude:: _FileUpload/_Upload.html + :caption: EXT:my_extension/Resources/Private/Templates/Blog/New.html + +You can actually easily also allow to remove already uploaded files: + +.. literalinclude:: _FileUpload/_UploadDelete.html + :caption: EXT:my_extension/Resources/Private/Templates/Blog/New.html + +The controller action part with persisting the data needs no further custom code, +Extbase can automatically do all the Domain Model handling on its own. The TCA can +also stay the same as configured for simply read-access to a Domain Model. + +The actual file upload processing is performed just before Extbase persists a +Domain Model Entity, so only if the full validation has taken place and no errors +occurred. This means, if any error occurs, a user will have to re-upload a file. + +The implementation is done like this to prevent stale temporary files that would +need cleanup or could raise issues with Denial of Service. + + +.. _extbase_fileupload_attribute: + +Reference for the :php:`FileUpload` PHP attribute +------------------------------------------------- + +File uploads can be validated by the following rules: + +* minimum and maximum file count +* minimum and maximum file size +* allowed MIME types +* image dimensions (for image uploads) + +Additionally, it is ensured, that the filename given by the client is valid, +meaning that no invalid characters (null-bytes) are added and that the file +does not contain an invalid file extension. The API has support for custom +validators, which can be created on demand. + +To avoid complexity and maintain data integrity, a file upload is only +processed if the validation of all properties of a domain model is successful. +In this first implementation, file uploads are not persisted/cached temporarily, +so this means in any case of a validation failure ("normal" validators and file upload +validation) a file upload must be performed again by users. + +Possible future enhancements of this functionality could enhance the existing +`#[FileUpload]` attribute/annotation with configuration like a temporary storage +location, or specifying additional custom validators (which can be done via the PHP-API as +described below) + +.. _extbase_fileupload_attribute_configuration: +File upload configuration with the `FileUpload` attribute +--------------------------------------------------------- + +File upload for a property of a domain model can be configured using the +newly introduced :php:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute. + +Example: + +.. code-block:: php + + #[FileUpload([ + 'validation' => [ + 'required' => true, + 'maxFiles' => 1, + 'fileSize' => ['minimum' => '0K', 'maximum' => '2M'], + 'allowedMimeTypes' => ['image/jpeg', 'image/png'], + ], + 'uploadFolder' => '1:/user_upload/files/', + ])] + protected ?FileReference $file = null; + +All configuration settings of the +:php:`\TYPO3\CMS\Extbase\Mvc\Controller\FileUploadConfiguration` object can +be defined using the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` +attribute. It is however not possible +to add custom validators using the +:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute, which you +can achieve with a manual configuration as shown below. + +The currently available configuration array keys are: + +* `validation` (:php:`array` with keys `required`, `maxFiles`, `minFiles`, + `fileSize`, `allowedMimeTypes`, `imageDimensions`, see + :ref:`extbase_fileupload_attribute-validationkeys`) +* `uploadFolder` (:php:`string`, destination folder) +* `duplicationBehavior` (:php:`object`, behaviour when file exists) +* `addRandomSuffix` (:php:`bool`, suffixing files) +* `createUploadFolderIfNotExist` (:php:`bool`, whether to create missing + directories) + +It is also possible to use the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` annotation to configure +file upload properties, but it is recommended to use the +:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute due to better readability. + +.. _extbase_fileupload_attribute-manual-configuration: + +Manual file upload configuration +-------------------------------- + +A file upload configuration can also be created manually and should be +done in the :php:`initialize*Action`. + +Example: + +.. code-block:: php + + public function initializeCreateAction(): void + { + $mimeTypeValidator = GeneralUtility::makeInstance(MimeTypeValidator::class); + $mimeTypeValidator->setOptions(['allowedMimeTypes' => ['image/jpeg']]); + + $fileHandlingServiceConfiguration = $this->arguments->getArgument('myArgument')->getFileHandlingServiceConfiguration(); + $fileHandlingServiceConfiguration->addFileUploadConfiguration( + (new FileUploadConfiguration('myPropertyName')) + ->setRequired() + ->addValidator($mimeTypeValidator) + ->setMaxFiles(1) + ->setUploadFolder('1:/user_upload/files/') + ); + + $this->arguments->getArgument('myArgument')->getPropertyMappingConfiguration()->skipProperties('myPropertyName'); + } + + +.. _extbase_fileupload_attribute-options: + +Configuration options for file uploads +-------------------------------------- + +The configuration for a file upload is defined in a +:php:`FileUploadConfiguration` object. + +This object contains the following configuration options. + +.. hint:: + + The appropriate setter methods or configuration + keys can best be inspected inside that class definition. + +.. _extbase_fileupload_attribute-property-name: + +Property name: +~~~~~~~~~~~~~~ + +Defines the name of the property of a domain model to which the file upload +configuration applies. The value is automatically retrieved when using +the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute. If the +:php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\FileUploadConfiguration` object +is created manually, it must be set using the :php:`$propertyName` +constructor argument. + +.. _extbase_fileupload_attribute-validation: + +Validation: +~~~~~~~~~~~ + +File upload validation is defined in an array of validators in the +:php-short:`\TYPO3\CMS\Extbase\Mvc\Controller\FileUploadConfiguration` object. The validator +:php:`\TYPO3\CMS\Extbase\Validation\Validator\FileNameValidator`, +which ensures that no executable PHP files can +be uploaded, is added by default if the file upload configuration object +is created using the +:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute. + +In addition, Extbase includes the following validators to validate an +:php-short:`\TYPO3\CMS\Core\Http\UploadedFile` object: + +* :php:`\TYPO3\CMS\Extbase\Validation\Validator\FileSizeValidator` +* :php:`\TYPO3\CMS\Extbase\Validation\Validator\MimeTypeValidator` +* :php:`\TYPO3\CMS\Extbase\Validation\Validator\ImageDimensionsValidator` + +Those validators can either be configured with the +:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute or added +manually to the configuration object +with the :php:`addValidator` method. + +.. _extbase_fileupload_attribute-required: + +Required: +~~~~~~~~~ + +Defines whether a file must be uploaded. If it is set to `true`, the +:php:`minFiles` configuration is set to `1`. + +.. _extbase_fileupload_attribute-minimum-files: + +Minimum files: +~~~~~~~~~~~~~~ + +Defines the minimum amount of files to be uploaded. + +.. _extbase_fileupload_attribute-maximum-files: + +Maximum files: +~~~~~~~~~~~~~~ + +Defines the maximum amount of files to be uploaded. + +.. _extbase_fileupload_attribute-upload-folder: + +Upload folder: +~~~~~~~~~~~~~~ + +Defines the upload path for the file upload. This configuration expects a +storage identifier (e.g. :php:`1:/user_upload/folder/`). If the given target +folder in the storage does not exist, it is created automatically. + +.. _extbase_fileupload_attribute-upload-folder-creation: + +Upload folder creation, when missing: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The default creation of a missing storage folder can be disabled via the +configuration attribute :php:`createUploadFolderIfNotExist` +(:php:`bool`, default :php:`true`). + +.. _extbase_fileupload_attribute-random-suffix: + +Add random suffix: +~~~~~~~~~~~~~~~~~~ + +When enabled, the filename of an uploaded and persisted file will contain a +random 16 char suffix. As an example, an uploaded file named +:php:`job-application.pdf` will be persisted as +:php:`job-application-.pdf` in the upload folder. + +The default value for this configuration is :php:`true` and it is recommended +to keep this configuration active. + +This configuration only has an effect when uploaded files are persisted. + +.. _extbase_fileupload_attribute-duplication-behavior: + +Duplication behavior: +~~~~~~~~~~~~~~~~~~~~~ + +Defines the FAL behavior, when a file with the same name exists in the target +folder. Possible values are :php:`DuplicationBehavior::RENAME` (default), +:php:`DuplicationBehavior::REPLACE` and :php:`DuplicationBehavior::CANCEL`. + + +.. _extbase_fileupload_attribute-configuration-change: + +Modifying existing configuration +-------------------------------- + +File upload configuration defined by the +:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute can be +changed in the :php:`initialize*Action`. + +Example: + +.. code-block:: php + + public function initializeCreateAction(): void + { + $validator = GeneralUtility::makeInstance(MyCustomValidator::class); + + $argument = $this->arguments->getArgument('myArgument'); + $configuration = $argument->getFileHandlingServiceConfiguration()->getFileUploadConfigurationForProperty('file'); + $configuration?->setMinFiles(2); + $configuration?->addValidator($validator); + $configuration?->setUploadFolder('1:/user_upload/custom_folder'); + } + +The example shows how to modify the file upload configuration for the argument +:php:`item` and the property :php:`file`. The minimum amount of files to be +uploaded is set to :php:`2` and a custom validator is added. + +To remove all defined validators except the :php:`DenyPhpUploadValidator`, use +the :php:`resetValidators()` method. + + +.. _extbase_fileupload_attribute-typoscript: + +Using TypoScript configuration for file uploads configuration +------------------------------------------------------------- + +When a file upload configuration for a property has been added using the +:php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute, it may be +required make the upload folder or +other configuration options configurable with TypoScript. + +Extension authors should use the :php:`initialize*Action` to apply settings +from TypoScript to a file upload configuration. + + +Example: + +.. code-block:: php + + public function initializeCreateAction(): void + { + $argument = $this->arguments->getArgument('myArgument'); + $configuration = $argument->getFileHandlingServiceConfiguration()->getConfigurationForProperty('file'); + $configuration?->setUploadFolder($this->settings['uploadFolder'] ?? '1:/fallback_folder'); + } + + +.. _extbase_fileupload_attribute-validationkeys: + +File upload validation +---------------------- + +Each uploaded file can be validated against a configurable set of validators. +The :php:`validation` section of the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute allows to +configure commonly used validators using a configuration shorthand. + +The following validation rules can be configured in the :php:`validation` +section of the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute: + +* :php:`required` +* :php:`minFiles` +* :php:`maxFiles` +* :php:`fileSize` +* :php:`allowedMimeTypes` +* :php:`imageDimensions` + +Example: + +.. code-block:: php + + #[FileUpload([ + 'validation' => [ + 'required' => true, + 'maxFiles' => 1, + 'fileSize' => ['minimum' => '0K', 'maximum' => '2M'], + 'allowedMimeTypes' => ['image/jpeg'], + 'imageDimensions' => ['maxWidth' => 4096, 'maxHeight' => 4096] + ], + 'uploadFolder' => '1:/user_upload/extbase_single_file/', + ])] + +Extbase will internally use the Extbase file upload validators for +:php:`fileSize`, :php:`allowedMimeTypes` and :php:`imageDimensions` validation. + +Custom validators can be created according to project requirements and must +extend the Extbase :php-short:`\TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator`. +The value to be validated is +always a PSR-7 :php-short:`\TYPO3\CMS\Core\Http\UploadedFile` object. +Custom validators can however not +be used in the :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload` attribute +and must be configured manually. + + +.. _extbase_fileupload_attribute-deletion: + +Deletion of uploaded files and file references +---------------------------------------------- + +The new Fluid ViewHelper +:ref:`Form.uploadDeleteCheckbox ViewHelper ` +can be used to show a "delete file" checkbox in a form. + +Example for object with :php-short:`\TYPO3\CMS\Core\Resource\FileReference` property: + +.. code-block:: php + + + +Example for an object with an :php:`ObjectStorage` property, +containing multiple files and allowing to delete the first one +(iteration is possible within Fluid, to do that for every object of the collection): + +.. code-block:: php + + + +Extbase will then handle file deletion(s) before persisting a validated +object. It will: + +* validate that minimum and maximum file upload configuration for the affected + property is fulfilled (only if the property has a :php-short:`\TYPO3\CMS\Extbase\Annotation\FileUpload`) +* delete the affected :php:`sys_file_reference` record +* delete the affected file + +Internally, Extbase uses :php:`FileUploadDeletionConfiguration` objects to track +file deletions for properties of arguments. Files are deleted directly without +checking whether the current file is referenced by other objects. + +Apart from using this ViewHelper, it is of course still possible to manipulate +:php-short:`\TYPO3\CMS\Core\Resource\FileReference` properties with custom logic before persistence. + +.. _extbase_fileupload_attribute-psr-event: + +ModifyUploadedFileTargetFilenameEvent +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :php-short:`\TYPO3\CMS\Extbase\Event\Service\ModifyUploadedFileTargetFilenameEvent` +allows event listeners to +alter a filename of an uploaded file before it is persisted. + +Event listeners can use the method `getTargetFilename()` to retrieve the filename +used for persistence of a configured uploaded file. The filename can then be +adjusted via `setTargetFilename()`. The relevant configuration can be retrieved +via `getConfiguration()`. diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/Index.rst b/Documentation/ExtensionArchitecture/Extbase/Reference/Index.rst index 9e1e115570..4fd5631bbe 100644 --- a/Documentation/ExtensionArchitecture/Extbase/Reference/Index.rst +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/Index.rst @@ -20,6 +20,7 @@ Extbase reference TypoScriptConfiguration Annotations Validation + FileUpload Caching Localization UriArguments diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_ApiUpload.php b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_ApiUpload.php new file mode 100644 index 0000000000..5e27fc925e --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_ApiUpload.php @@ -0,0 +1,59 @@ +resourceFactory->retrieveFileOrFolderObject($falIdentifier); + $fileObject = $falFolder->addFile( + $yourFile, + basename($yourFile), + DuplicationBehavior::REPLACE); + + // Initialize a new storage object + $newObject = [ + 'uid_local' => $fileObject->getUid(), + 'uid_foreign' => StringUtility::getUniqueId('NEW'), + 'uid' => StringUtility::getUniqueId('NEW'), + 'crop' => null, + ]; + + // Create the FileReference Object + $fileReference = $this->resourceFactory->createFileReferenceObject($newObject); + + // Port the FielReference Object to an Extbase FileReference + $fileReferenceObject = GeneralUtility::makeInstance(FileReference::class); + $fileReferenceObject->setOriginalResource($fileReference); + + // Persist the created file reference object to our Blog model + $blog->setSingleFile($fileReferenceObject); + $this->blogRepository->update($blog); + + // Note: For multiple files, a wrapping ObjectStorage would be needed + } +} + diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Blog.php b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Blog.php new file mode 100644 index 0000000000..3bd461999f --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Blog.php @@ -0,0 +1,54 @@ + + */ + protected ObjectStorage $multipleFiles; + + // When using ObjectStorages, it is vital to initialize these. + public function __construct() + { + $this->initializeObjectStorage(); + } + + public function initializeObjectStorage(): void + { + $this->multipleFiles = new ObjectStorage(); + } + + // Typical getters + public function getSingleFile(): ?FileReference + { + return $this->singleFile; + } + + public function getMultipleFiles(): ObjectStorage + { + return $this->multipleFiles; + } + + // For later examples, the setters: + public function setSingleFile(?FileReference $singleFile): void + { + $this->singleFile = $singleFile; + } + + public function setMultipleFiles(ObjectStorage $files): void + { + $this->multipleFiles = $files; + } +} diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_BlogController.php b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_BlogController.php new file mode 100644 index 0000000000..bc5ff37683 --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_BlogController.php @@ -0,0 +1,26 @@ +view->assign('blog', $blog); + + return $this->htmlResponse(); + } +} diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_BlogEnhanced.php b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_BlogEnhanced.php new file mode 100644 index 0000000000..4709cb4b69 --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_BlogEnhanced.php @@ -0,0 +1,76 @@ + [ + 'required' => true, + 'maxFiles' => 1, + 'fileSize' => ['minimum' => '0K', 'maximum' => '2M'], + 'allowedMimeTypes' => ['image/jpeg'], + 'imageDimensions' => ['maxWidth' => 4096, 'maxHeight' => 4096] + ], + 'uploadFolder' => '1:/user_upload/extbase_single_file/', + 'addRandomSuffix' => false, + 'duplicationBehavior' => DuplicationBehavior::RENAME, + ])] + protected ?FileReference $singleFile = null; + + #[FileUpload([ + 'validation' => [ + 'required' => true, + 'fileSize' => ['minimum' => '0K', 'maximum' => '2M'], + 'allowedMimeTypes' => ['image/jpeg'] + ], + 'uploadFolder' => '1:/user_upload/extbase_single_file/' + ])] + /** + * A collection of files. + * @var ObjectStorage + */ + protected ObjectStorage $multipleFiles; + + // When using ObjectStorages, it is vital to initialize these. + public function __construct() + { + $this->initializeObjectStorage(); + } + + public function initializeObjectStorage(): void + { + $this->multipleFiles = new ObjectStorage(); + } + + // Typical getters + public function getSingleFile(): ?FileReference + { + return $this->singleFile; + } + + public function getMultipleFiles(): ObjectStorage + { + return $this->multipleFiles; + } + + // Typical setters + public function setSingleFile(?FileReference $singleFile): void + { + $this->singleFile = $singleFile; + } + + public function setMultipleFiles(ObjectStorage $files): void + { + $this->multipleFiles = $files; + } +} diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Show.html b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Show.html new file mode 100644 index 0000000000..792d292e0c --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Show.html @@ -0,0 +1,16 @@ + + + + + +

Single image:

+ + +

Multiple images:

+ + + + +

Access first image of multiple images:

+ +
diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Upload.html b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Upload.html new file mode 100644 index 0000000000..ce7e8147cc --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_Upload.html @@ -0,0 +1,23 @@ + + + + + + +
+

Single file

+ +
+ +
+

Multiple files

+ +
+ +
+ +
+
+
diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_UploadDelete.html b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_UploadDelete.html new file mode 100644 index 0000000000..c5b0009745 --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_UploadDelete.html @@ -0,0 +1,45 @@ + + + + + + +
+

Single file

+ + +
+ + +
+
+ + +
+ +
+

Multiple files

+ + + +
+ + +
+
+
+ + +
+ +
+ +
+
+
diff --git a/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_tx_myextension_domain_model_blog.php b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_tx_myextension_domain_model_blog.php new file mode 100644 index 0000000000..7d4837b664 --- /dev/null +++ b/Documentation/ExtensionArchitecture/Extbase/Reference/_FileUpload/_tx_myextension_domain_model_blog.php @@ -0,0 +1,27 @@ + [ + // .. usual TCA fields + ], + 'columns' => [ + // ... usual TCA columns + 'singleFile' => [ + 'exclude' => true, + 'label' => 'Single file', + 'config' => [ + 'type' => 'file', + 'maxitems' => 1, + 'allowed' => 'common-image-types', + ], + ], + 'multipleFiles' => [ + 'exclude' => true, + 'label' => 'Multiple files', + 'config' => [ + 'type' => 'file', + 'allowed' => 'common-image-types', + ], + ], + ], +];