The Dynamic Row Image Upload Magento module simplifies image management by allowing administrators to upload and organize multiple images directly within the Admin System Configuration using dynamic rows.
This module also ensures accuracy by validating for empty text fields, enhancing both functionality and user experience.
You can find the complete module on GitHub at Magelearn_DynamicFileUpload
Or Check the below images for a better understanding of the functionality of this module.
Let's start it by creating a custom extension.
Create a folder inside app/code/Magelearn/DynamicFileUpload
Add registration.php file in it:
1 2 3 4 5 6 7 | <?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Magelearn_DynamicFileUpload' , __DIR__ ); |
Add composer.json file in it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | { "name" : "magelearn/magento2-module-dynamic-file-upload" , "description" : "The Dynamic Row Image Upload Magento module enables administrators to upload and manage multiple images directly in Admin System Configuration with dynamic rows." , "type" : "magento2-module" , "license" : "Apache-2.0" , "authors" : [ { "name" : "Vijay Rami" , "email" : "vijaymrami@gmail.com" } ], "minimum-stability" : "dev" , "prefer-stable" : true, "version" : "1.0" , "require" : { "php" : ">=8.0.0" }, "repositories" : [ { "type" : "package" , "package" : { "name" : "magelearn/magento2-module-dynamic-file-upload" , "version" : "1.0" , "source" : { "type" : "git" , "reference" : "main" } } } ], "autoload" : { "files" : [ "registration.php" ], "psr-4" : { "Magelearn\\DynamicFileUpload\\" : "" } } } |
Add etc/module.xml file in it:
1 2 3 4 5 6 7 8 | <? xml version = "1.0" ?> < config xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation = "urn:magento:framework:Module/etc/module.xsd" > < module name = "Magelearn_DynamicFileUpload" setup_version = "1.0.0" > < sequence > < module name = "Magento_Backend" /> </ sequence > </ module > </ config > |
Now to give the option at System configuration at admin,
we will add app/code/Magelearn/DynamicFileUpload/etc/adminhtml/system.xml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <? xml version = "1.0" ?> xsi:noNamespaceSchemaLocation = "urn:magento:module:Magento_Config:etc/system_file.xsd" > < system > < tab id = "magelearn" translate = "label" sortOrder = "400" > < label >Magelearn Modules</ label > </ tab > < section id = "swatch" translate = "label" type = "text" sortOrder = "300" showInDefault = "1" showInWebsite = "1" showInStore = "1" > < class >separator-top</ class > < label >Dynamic Image Upload</ label > < tab >magelearn</ tab > < resource >Magelearn_DynamicFileUpload::config</ resource > < group id = "dynamic_row_image" translate = "label" type = "text" sortOrder = "10" showInDefault = "1" showInWebsite = "1" showInStore = "1" > < field id = "images" translate = "label" sortOrder = "100" showInDefault = "1" showInWebsite = "1" showInStore = "1" > < label >Dynamic Images</ label > < comment ></ comment > < frontend_model >Magelearn\DynamicFileUpload\Block\Adminhtml\Form\Field\ImageFieldsList</ frontend_model > < backend_model >Magelearn\DynamicFileUpload\Model\Config\Backend\Serialized\ImageArraySerialized</ backend_model > </ field > </ group > </ section > </ system > </ config > |
We will add etc/adminhtml/di.xml file to provide proper configurations for image extensions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <? xml version = "1.0" ?> xsi:noNamespaceSchemaLocation = "urn:magento:framework:ObjectManager/etc/config.xsd" > < type name = "Magelearn\DynamicFileUpload\Model\ImageUploader" > < arguments > < argument name = "allowExtensions" xsi:type = "array" > < item name = "jpg" xsi:type = "string" >jpg</ item > < item name = "jpeg" xsi:type = "string" >jpeg</ item > < item name = "gif" xsi:type = "string" >gif</ item > < item name = "png" xsi:type = "string" >png</ item > < item name = "webp" xsi:type = "string" >webp</ item > </ argument > </ arguments > </ type > </ config > |
As per Highlighted code in etc/adminhtml/system.xml file,
We will add app/code/Magelearn/DynamicFileUpload/Block/Adminhtml/Form/Field/ImageFieldsList.php file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <?php namespace Magelearn\DynamicFileUpload\Block\Adminhtml\Form\Field; class ImageFieldsList extends \Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray { protected $imageRenderer ; /** * Initialise form fields * * @return void */ protected function _prepareToRender() { $this ->addImageColumn(); $this ->addNameColumn(); $this ->_addAfter = false; $this ->_addButtonLabel = __( 'Add Category' ); parent::_prepareToRender(); } private function addImageColumn() { $this ->addColumn( 'image' , [ 'label' => __( 'Category Image' ), 'renderer' => $this ->getImageRenderer(), 'class' => 'required-entry' ]); } private function addNameColumn() { $this ->addColumn( 'name' , [ 'label' => __( 'Category Name' ), 'class' => 'required-entry' ]); } protected function getImageRenderer() { if (! $this ->imageRenderer) { $this ->imageRenderer = $this ->getLayout()->createBlock( \Magelearn\DynamicFileUpload\Block\Adminhtml\Form\Field\ImageColumn:: class , '' , [ 'data' => [ 'is_render_to_js_template' => true]] ); } return $this ->imageRenderer; } } |
Similarly, to render the image column, we will add
app/code/Magelearn/DynamicFileUpload/Block/Adminhtml/Form/Field/ImageColumn.php file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <?php namespace Magelearn\DynamicFileUpload\Block\Adminhtml\Form\Field; use Magento\Framework\View\Element\AbstractBlock; use Magelearn\DynamicFileUpload\Block\Adminhtml\ImageButton; class ImageColumn extends AbstractBlock { public function setInputName(string $value ) { return $this ->setName( $value ); } public function setInputId(string $value ) { return $this ->setId( $value ); } protected function _toHtml(): string { $imageButton = $this ->getLayout() ->createBlock(ImageButton:: class ) ->setData( 'id' , $this ->getId()) ->setData( 'name' , $this ->getName()); return $imageButton ->toHtml(); } protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element ) { $html = '' ; // Assuming 'image' is the field name where the image URL is stored $imageUrl = $element ->getValue(); if ( $imageUrl ) { $html .= '<img src="' . $imageUrl . '" alt="' . __( 'Category Image' ) . '" style="max-width: 100px; max-height: 100px;" />' ; } else { $html .= __( 'No Image' ); } return $html ; } } |
And as per highlighted code above, we will add our block file at
Block/Adminhtml/ImageButton.php file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | <?php declare (strict_types=1); namespace Magelearn\DynamicFileUpload\Block\Adminhtml; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\Framework\UrlInterface; class ImageButton extends \Magento\Backend\Block\Template { protected $_template = 'Magelearn_DynamicFileUpload::config/array_serialize/image.phtml' ; /** * @var Filesystem */ private $filesystem ; /** * @var UrlInterface */ private $url ; private $mediaDirectory ; private $assetRepository ; public function __construct( \Magento\Backend\Block\Template\Context $context , Filesystem $filesystem , UrlInterface $url , \Magento\Framework\View\Asset\Repository $assetRepository , array $data = [] ) { $this ->assetRepository = $assetRepository ; $this ->filesystem = $filesystem ; $this ->url = $url ; parent::__construct( $context , $data ); } public function getAssertRepository(): \Magento\Framework\View\Asset\Repository { return $this ->assetRepository; } /** * @return string */ public function getImageUrl() { return $this ->url->getBaseUrl([ '_type' => UrlInterface::URL_TYPE_MEDIA]); } public function getMediaDirectory() { if ( $this ->mediaDirectory === null) { $this ->mediaDirectory = $this ->filesystem->getDirectoryWrite(DirectoryList::MEDIA); } return $this ->mediaDirectory; } } |
Now Add the Highlighted template file at view/adminhtml/templates/config/array_serialize/image.phtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <?php /*** @var \Magelearn\DynamicFileUpload\Block\Adminhtml\ImageButton $block */ $css = $block->getAssertRepository()->createAsset( "Magelearn_DynamicFileUpload::css/image_button.css" ); ?> <link rel= "stylesheet" type= "text/css" media= "all" href= "<?php /* @escapeNotVerified */echo $css->getUrl() ?>" /> <div class= "upload-file" data-id= "<?=$block->getId()?>" > <div class= "upload-file__block upload-file__block_first" > <img class= "upload-file__block__img" id= "swatch_image_image_<?= $block->getId() ?>" src= "" > </div> <div class= "upload-file__block" > <input class= "upload-file__input" hidden type= "file" name= "<?= $block->getName() ?>" id= "swatch_image_input_<?= $block->getId() ?>" value= "" /> <label class= "upload-file__label" for = "swatch_image_input_<?= $block->getId() ?>" > <?= __( "File" ) ?> </label> </div> <input class= "upload-file__input" type= "hidden" id= "<?=$block->getId()?>" > </div> <script type= "text/javascript" > require([ "jquery" ], function (jq) { jq( function () { const id = "<?=$block->getId()?>" const imageId = "swatch_image_image_<?=$block->getId()?>" const data = jq( "#" + id).val(); const image_url = "<?=$block->getImageUrl()?>" console.log(data, id); if (data) { jq( "#" + imageId).attr( "src" , image_url + data) jq( "#" + imageId).attr( "value" , data) } // Handle file input change event jq( "#swatch_image_input_<?= $block->getId() ?>" ).on( "change" , function (event) { const file = event.target.files[0]; // Get the uploaded file if (file) { const reader = new FileReader(); // Create a FileReader to read the file reader.onload = function (e) { const imageId = "swatch_image_image_<?= $block->getId() ?>" ; jq( "#" + imageId).attr( "src" , e.target.result); // Set the image src to the uploaded file }; reader.readAsDataURL(file); // Read the file as a data URL } }); }); }); </script> |
We will add our CSS file at view/adminhtml/web/css/image_button.css
Now as per highlighted in etc/adminhtml/system.xml file,
We will add our backend_model class at app/code/Magelearn/DynamicFileUpload/Model/Config/Backend/Serialized/ImageArraySerialized.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | <?php declare (strict_types=1); namespace Magelearn\DynamicFileUpload\Model\Config\Backend\Serialized; use Magento\Framework\Serialize\Serializer\Json; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; use Magento\Config\Model\Config\Backend\Serialized\ArraySerialized; use Magento\Framework\Exception\LocalizedException; use Psr\Log\LoggerInterface; class ImageArraySerialized extends ArraySerialized { /** * @var \Magelearn\DynamicFileUpload\Model\ImageUploaderFactory */ private $imageUploaderFactory ; /** * @var \Magelearn\DynamicFileUpload\Model\Config\ImageConfig */ private $imageConfig ; /** * @var Filesystem */ protected $filesystem ; /** * @var LoggerInterface */ private $logger ; /** * @var string */ private const UPLOAD_DIR = 'magelearn/dynamicfileupload' ; /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList * @param \Magelearn\DynamicFileUpload\Model\Config\ImageConfig $imageConfig * @param \Magelearn\DynamicFileUpload\Model\ImageUploaderFactory $imageUploaderFactory * @param Filesystem $filesystem * @param LoggerInterface $logger * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $data * @param Json|null $serializer */ public function __construct( \Magento\Framework\Model\Context $context , \Magento\Framework\Registry $registry , \Magento\Framework\App\Config\ScopeConfigInterface $config , \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList , \Magelearn\DynamicFileUpload\Model\Config\ImageConfig $imageConfig , \Magelearn\DynamicFileUpload\Model\ImageUploaderFactory $imageUploaderFactory , Filesystem $filesystem , LoggerInterface $logger , \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [], Json $serializer = null ) { $this ->imageUploaderFactory = $imageUploaderFactory ; $this ->filesystem = $filesystem ; $this ->imageConfig = $imageConfig ; $this ->logger = $logger ; parent::__construct( $context , $registry , $config , $cacheTypeList , $resource , $resourceCollection , $data , $serializer ); } /** * Process data before saving * * @return ArraySerialized * @throws LocalizedException */ public function beforeSave(): ArraySerialized { try { $value = $this ->getValue(); if ( is_array ( $value )) { $value = $this ->processImageUpload( $value ); $this ->setValue( $value ); } return parent::beforeSave(); } catch (\Exception $e ) { throw new LocalizedException(__( 'Error processing images: %1' , $e ->getMessage())); } } /** * Process image upload and map rows * * @param array $rows * @return array * @throws LocalizedException */ private function processImageUpload( array $rows ): array { try { $mediaDirectory = $this ->filesystem->getDirectoryRead(DirectoryList::MEDIA); $destinationPath = $mediaDirectory ->getAbsolutePath(self::UPLOAD_DIR); // Create image uploader instance $imageUploader = $this ->imageUploaderFactory->create([ 'path' => $this ->getPath(), 'uploadDir' => $destinationPath , ]); // Upload files and get results $uploadedFiles = $imageUploader ->upload(); // Get existing configuration $existingConfig = $this ->imageConfig->getImagesConfig(); return $this ->processRows( $rows , $uploadedFiles , $existingConfig ); } catch (\Exception $e ) { throw new LocalizedException(__( 'Failed to process image upload: %1' , $e ->getMessage())); } } /** * Process rows with uploaded files and existing configuration * * @param array $rows * @param array $uploadedFiles * @param array $existingConfig * @return array */ private function processRows( array $rows , array $uploadedFiles , array $existingConfig ): array { foreach ( $rows as $id => & $data ) { if (isset( $uploadedFiles [ $id ])) { // New file uploaded $data [ 'image' ] = $uploadedFiles [ $id ][ $id ]; } elseif (!isset( $existingConfig [ $id ])) { // Row doesn't exist in config and no new file unset( $rows [ $id ]); } elseif (isset( $data [ 'image' ]) && is_array ( $data [ 'image' ])) { // Existing image, preserve from config $data = $this ->preserveExistingImage( $data , $existingConfig [ $id ]); } } return $rows ; } /** * Preserve existing image data * * @param array $row * @param array $configData * @return array */ private function preserveExistingImage( array $row , array $configData ): array { if (isset( $row [ 'image' ]) && is_array ( $row [ 'image' ])) { $row [ 'image' ] = $configData [ 'image' ]; } return $row ; } /** * Get upload path * * @return string */ private function getPath(): string { return self::UPLOAD_DIR; } } |
And As per Highlighted code above, we will add app/code/Magelearn/DynamicFileUpload/Model/Config/ImageConfig.php file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <?php declare (strict_types=1); namespace Magelearn\DynamicFileUpload\Model\Config; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\ScopeInterface; use Magento\Framework\Serialize\SerializerInterface; class ImageConfig { const XML_PATH_IMAGES = 'swatch/dynamic_row_image/images' ; /** * @var ScopeConfigInterface */ private $scopeConfig ; /** * @var SerializerInterface */ private $serializer ; /** * @param ScopeConfigInterface $scopeConfig * @param SerializerInterface $serializer */ public function __construct( ScopeConfigInterface $scopeConfig , SerializerInterface $serializer ) { $this ->scopeConfig = $scopeConfig ; $this ->serializer = $serializer ; } /** * Get serialized images configuration * * @param string $storeId * @return array * @throws \InvalidArgumentException */ public function getImagesConfig( $storeId = null): array { $value = $this ->scopeConfig->getValue( self::XML_PATH_IMAGES, ScopeInterface::SCOPE_STORE, $storeId ); try { return $value ? $this ->serializer->unserialize( $value ) : []; } catch (\InvalidArgumentException $e ) { return []; } } } |
And our ImageUploader class at app/code/Magelearn/DynamicFileUpload/Model/ImageUploader.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | <?php declare (strict_types=1); namespace Magelearn\DynamicFileUpload\Model; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Filesystem; use Magento\MediaStorage\Model\File\Uploader; use Psr\Log\LoggerInterface; class ImageUploader { private const MAX_FILE_SIZE = 2048000; // 2MB limit private const ALLOWED_MIME_TYPES = [ 'jpg' => 'image/jpeg' , 'jpeg' => 'image/jpeg' , 'gif' => 'image/gif' , 'png' => 'image/png' , 'webp' => 'image/webp' , ]; /** * @var ArrayFileModifier */ private $arrayFileModifier ; /** * @var \Magento\MediaStorage\Model\File\UploaderFactory */ private $uploaderFactory ; /** * @var string */ private $uploadDir ; /** * @var Filesystem */ protected $filesystem ; /** * @var LoggerInterface */ protected $logger ; /** * @var array */ private $allowExtensions ; /** * @param ArrayFileModifier $arrayFileModifier * @param \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory * @param Filesystem $filesystem * @param LoggerInterface $logger * @param string $uploadDir * @param array $allowExtensions */ public function __construct( ArrayFileModifier $arrayFileModifier , \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory , Filesystem $filesystem , LoggerInterface $logger , string $uploadDir = 'magelearn/dynamicfileupload' , array $allowExtensions = [ 'jpg' , 'jpeg' , 'gif' , 'png' , 'webp' ] ) { $this ->arrayFileModifier = $arrayFileModifier ; $this ->uploaderFactory = $uploaderFactory ; $this ->filesystem = $filesystem ; $this ->logger = $logger ; $this ->uploadDir = $uploadDir ; $this ->allowExtensions = array_intersect ( array_keys (self::ALLOWED_MIME_TYPES), $allowExtensions ); } /** * Upload files * * @return array * @throws LocalizedException */ public function upload(): array { try { $files = $this ->arrayFileModifier->modify(); if ( empty ( $files )) { return []; } return $this ->processFiles( $files ); } catch (\Exception $e ) { $this ->logger->critical( 'File upload error: ' . $e ->getMessage(), [ 'trace' => $e ->getTraceAsString()]); throw new LocalizedException(__( 'Error during file upload. Please try again.' )); } } /** * Process uploaded files * * @param array $files * @return array * @throws LocalizedException */ private function processFiles( array $files ): array { $result = []; $mediaDirectory = $this ->filesystem->getDirectoryRead(DirectoryList::MEDIA); $destinationPath = $mediaDirectory ->getAbsolutePath( $this ->uploadDir); foreach ( $files as $id => $file ) { try { if (!isset( $file [ 'tmp_name' ]) || ! file_exists ( $file [ 'tmp_name' ])) { throw new LocalizedException(__( 'File does not exist' )); } $this ->validateFile( $file ); $uploader = $this ->uploaderFactory->create([ 'fileId' => $id ]); $uploader ->setAllowedExtensions( $this ->allowExtensions); $uploader ->setAllowRenameFiles(true); $uploader ->setFilesDispersion(true); $uploader ->addValidateCallback( 'size' , $this , 'validateMaxSize' ); $uploadResult = $uploader ->save( $destinationPath ); if (! $uploadResult ) { throw new LocalizedException(__( 'File cannot be saved to path: %1' , $destinationPath )); } $result [ $id ] = $uploadResult ; $result [ $id ][ $id ] = 'magelearn/dynamicfileupload' . '/' . ltrim( $uploadResult [ 'file' ], '/' ); } catch (\Exception $e ) { $this ->logger->error(sprintf( 'Error uploading file %s: %s' , $id , $e ->getMessage() ), [ 'trace' => $e ->getTraceAsString()]); throw new LocalizedException( __( 'Failed to upload file %1: %2' , $id , $e ->getMessage()) ); } } return $result ; } /** * Validate uploaded file * * @param array $file * @return void * @throws LocalizedException */ private function validateFile( array $file ): void { // Basic file validation if (!isset( $file [ 'tmp_name' ]) || !isset( $file [ 'name' ])) { throw new LocalizedException(__( 'Invalid file data' )); } // Size validation $this ->validateMaxSize( $file [ 'tmp_name' ]); // MIME type validation $this ->validateImageType( $file [ 'tmp_name' ]); } /** * Validate image type * * @param string $filePath * @return bool * @throws LocalizedException */ private function validateImageType(string $filePath ): bool { $mimeType = mime_content_type( $filePath ); if (!in_array( $mimeType , self::ALLOWED_MIME_TYPES)) { throw new LocalizedException( __( 'Invalid image type. Allowed types: %1' , implode( ', ' , $this ->allowExtensions)) ); } return true; } /** * Validate max file size * * @param string $filePath * @return void * @throws LocalizedException */ public function validateMaxSize(string $filePath ): void { if (! file_exists ( $filePath )) { throw new LocalizedException(__( 'File does not exist' )); } if ( filesize ( $filePath ) > self::MAX_FILE_SIZE) { throw new LocalizedException( __( 'File size exceeds the maximum limit of %1MB.' , self::MAX_FILE_SIZE / 1024 / 1024) ); } } } |
And As per highlighted in above file, we will add
app/code/Magelearn/DynamicFileUpload/Model/ArrayFileModifier.php file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | <?php declare (strict_types=1); namespace Magelearn\DynamicFileUpload\Model; use Magento\Framework\App\RequestInterface; use Magento\Framework\Exception\LocalizedException; class ArrayFileModifier { /** * @var RequestInterface */ private $request ; /** * @var string */ private $requestName ; /** * @param RequestInterface $request * @param string $requestName */ public function __construct( RequestInterface $request , string $requestName = 'groups' ) { $this ->request = $request ; $this ->requestName = $requestName ; } /** * Modify file array structure * * @return array * @throws LocalizedException */ public function modify(): array { try { $requestFiles = $this ->parseRequest( $this ->request->getFiles( $this ->requestName) ); if ( empty ( $requestFiles )) { return []; } return $this ->processRequestFiles( $requestFiles ); } catch (\Exception $e ) { throw new LocalizedException(__( 'Error processing file upload request: %1' , $e ->getMessage())); } } /** * Process request files * * @param array $requestFiles * @return array */ private function processRequestFiles( array $requestFiles ): array { $files = []; foreach ( $requestFiles as $id => $file ) { $data = array_shift ( $file ); if (!isset( $data [ 'tmp_name' ]) || empty ( $data [ 'tmp_name' ])) { continue ; } $files [ $id ] = $data ; } $_FILES = $files ; return $files ; } /** * Parse request data * * @param array|null $requestFiles * @return array */ private function parseRequest(? array $requestFiles ): array { if ( $requestFiles === null) { return []; } if (isset( $requestFiles [ 'value' ])) { return $requestFiles [ 'value' ]; } if ( is_array ( $requestFiles )) { $firstElement = array_shift ( $requestFiles ); if ( is_array ( $firstElement )) { return $this ->parseRequest( $firstElement ); } } return $requestFiles ; } } |
0 Comments On "Effortlessly Manage Multiple Images in Magento with the Dynamic Row Image Upload Module"