Magento 2 UI Component form provides various options to display many form input fields. We can also create the image upload field with preview using UI Component. This article assumes you have a basic understanding about Magento 2 UI Component.
In the below example scenario i already have a custom admin form and i will highlight the relevant sections on image upload.
Rendering the Image Field
The fileUploadercomponent works internally by using jQuery file uploader.
To render the image field we need to define the field details in UI Component as shown in the below code snippet.
We need to specify the required options in the configuration like
- formElement – Should be defined as fileUploader
- elementTmpl – Template file for displaying the image upload field.
- maxFileSize – Allowed File Size in the custom form
- uploaderConfig – Ajax Controller URL which handles the upload function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<field name="featured_image"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="source" xsi:type="string">featured_image</item> <item name="label" xsi:type="string">Featured Image</item> <item name="visible" xsi:type="boolean">true</item> <item name="formElement" xsi:type="string">fileUploader</item> <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item> <item name="maxFileSize" xsi:type="number">4194304</item> <item name="required" xsi:type="boolean">false</item> <item name="uploaderConfig" xsi:type="array"> <item name="url" xsi:type="url" path="newsevents/article/upload/field/featured_image"/> </item> </item> </argument> </field> |
Handling the File upload in AJAX Controller
Once the image field is rendered the next step is to handle the image upload in AJAX controller. The Controller code snippet shown below will simply read the field param passed from the custom admin form and delegate the upload functionality to the model class “uploader”. Initially the uploaded image has to be stored in the temporary directory while no data is saved.
During the model data save operation, the image will be moved to permanent location
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 |
/** * Upload file controller action * * @return \Magento\Framework\Controller\ResultInterface */ public function execute() { try { $result = $this->uploader->saveFileToTmpDir($this->getFieldName()); $result['cookie'] = [ 'name' => $this->_getSession()->getName(), 'value' => $this->_getSession()->getSessionId(), 'lifetime' => $this->_getSession()->getCookieLifetime(), 'path' => $this->_getSession()->getCookiePath(), 'domain' => $this->_getSession()->getCookieDomain(), ]; } catch (\Exception $e) { $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()]; } return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result); } /** * @return string */ protected function getFieldName() { return $this->_request->getParam('field'); } |
Defining the Image Paths as Constants in Model Class
By Default all the uploaded images should be placed under pub/media directory. You need to create your sub
folder with the desired name under the pub/media directory.
The below constants should be assigned with the newly created subdirectory under pub/media folder.
1 2 3 4 5 |
const IMAGE_TMP_PATH = 'yourfoldername/tmp'; /** * @var string */ const IMAGE_PATH = 'yourfoldername'; |
Model Constructor initialization with required dependencies
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public function __construct( \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase, \Magento\Framework\Filesystem $filesystem, \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Psr\Log\LoggerInterface $logger, $baseTmpPath, $basePath, \Magento\Framework\ObjectManagerInterface $objectmanager, $allowedExtensions = [] ) { $this->coreFileStorageDatabase = $coreFileStorageDatabase; $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); $this->uploaderFactory = $uploaderFactory; $this->storeManager = $storeManager; $this->logger = $logger; $this->baseTmpPath = $baseTmpPath; $this->basePath = $basePath; $this->_objectManager = $objectmanager; $this->allowedExtensions = $allowedExtensions; } |
Passing Values using di.xml
The values for the above model class constructor arguments can also be passed via di.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="FeaturedImageUploader" type="Mydons\NewsEvents\Model\Uploader"> <arguments> <argument name="baseTmpPath" xsi:type="const">Mydons\NewsEvents\Model\Uploader::IMAGE_TMP_PATH</argument> <argument name="basePath" xsi:type="const">Mydons\NewsEvents\Model\Uploader::IMAGE_PATH</argument> <argument name="allowedExtensions" 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> </argument> </arguments> </virtualType> </config> |
The Getter and setter functions should be defined under the Model Class
Defining Image Upload function in Model Class
Below function is called from the AJAX controller, this will save the image in temporary directory defined.
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 |
public function saveFileToTmpDir($fileId) { $baseTmpPath = $this->getBaseTmpPath(); $uploader = $this->uploaderFactory->create(['fileId' => $fileId]); $uploader->setAllowedExtensions($this->getAllowedExtensions()); $uploader->setAllowRenameFiles(true); $uploader->setFilesDispersion(true); $result = $uploader->save($this->mediaDirectory->getAbsolutePath($baseTmpPath)); if (!$result) { throw new LocalizedException( __('File can not be saved to the destination folder.') ); } /** * Workaround for prototype 1.7 methods "isJSON", "evalJSON" on Windows OS */ $result['tmp_name'] = str_replace('\\', '/', $result['tmp_name']); $result['path'] = str_replace('\\', '/', $result['path']); $result['url'] = $this->getBaseUrl() . $this->getFilePath($baseTmpPath, $result['file']); return $result; } |
Image upload Preview Output
So far we have covered only the basics of image preview, still there are few more steps to be implemented like saving the image file name in database, rendering the saved image from database etc.
Considering the length of blog post, i will try to cover the remaining portions in another followup tutorial.