Magento, Magento 2

How to Upload Image using UI Component in Magento 2

How to Upload Image using UI Component in Magento 2

In this tutorial, I will explain you about how to upload image using UI component in Magento 2. Magento 2 provides many UI components field and image uploader is one of them.

Here, Let’s start example step by step to add image uploader. For that, you need to create UI form. You can get reference from below links :

1) Firstly, Add this UI component image field in your UI form :

<!--
/**
 * Created By : Rohan Hapani
 */
-->
<field name="logo">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="dataType" xsi:type="string">string</item>
            <item name="source" xsi:type="string">helloworld</item>
            <item name="label" xsi:type="string" translate="true">Logo</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="previewTmpl" xsi:type="string">RH_Helloworld/image-preview</item>
            <item name="required" xsi:type="boolean">false</item>
            <item name="sortOrder" xsi:type="number">40</item>
            <item name="uploaderConfig" xsi:type="array">
                <item name="url" xsi:type="url" path="rh_helloworld/index/uploader"/>
            </item>
        </item>
    </argument>
</field>

2) Then, Create image-preview.html template file at app/code/RH/Helloworld/view/adminhtml/web/template/ for preview image :

<!--
/**
 * Created By : Rohan Hapani
 */
-->
<div class="file-uploader-summary">
    <div class="file-uploader-preview">
        <a attr="href: $parent.getFilePreview($file)" target="_blank">
            <img class="preview-image" tabindex="0" event="load: $parent.onPreviewLoad.bind($parent)" attr=" src: $parent.getFilePreview($file), alt: $file.name">
        </a> 
        <div class="actions">
            <button type="button" class="action-remove" data-role="delete-button" attr="title: $t('Delete image')" click="$parent.removeFile.bind($parent, $file)">
                <span translate="'Delete image'"/>
            </button>
        </div>
    </div>
    <div class="file-uploader-filename" text="$file.name"/>
    <div class="file-uploader-meta">
        <text args="$file.previewWidth"/>
        x
        <text args="$file.previewHeight"/>
   </div>
</div>

3) After, Create Virtual type for Image Uploader file di.xml at app/code/RH/Helloworld/etc/ and paste below code :

<!--
/**
 * Created By : Rohan Hapani
 */
-->
<!-- Image Uploader -->
<virtualType name="VirtualTypeName" type="Magento\Catalog\Model\ImageUploader">
   <arguments>
      <argument name="baseTmpPath" xsi:type="string">logo/image</argument>
      <argument name="basePath" xsi:type="string">logo/image</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>
<type name="RH\Helloworld\Controller\Adminhtml\Index\Uploader">
   <arguments>
      <argument name="imageUploader" xsi:type="object">VirtualTypeName</argument>
   </arguments>
</type>
<!-- End Image Uploader -->

4) Then, Create Controller file Uploader.php for Save Image at app/code/RH/Helloworld/Controller/Adminhtml/Index/ and paste the below code :

<?php
/**
 * Created By : Rohan Hapani
 */
namespace RH\Helloworld\Controller\Adminhtml\Index;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Controller\ResultFactory;

class Uploader extends \Magento\Backend\App\Action

{
    /**
     * Image uploader
     * @var \Magento\Catalog\Model\ImageUploader
     */
    protected $imageUploader;

    /**
     * @var \Magento\Framework\Filesystem
     */
    protected $filesystem;

    /**
     * @var \Magento\Framework\Filesystem\Io\File
     */
    protected $fileIo;

    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * Upload constructor.
     * @param \Magento\Backend\App\Action\Context        $context
     * @param \Magento\Catalog\Model\ImageUploader       $imageUploader
     * @param \Magento\Framework\Filesystem              $filesystem
     * @param \Magento\Framework\Filesystem\Io\File      $fileIo
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Catalog\Model\ImageUploader $imageUploader,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\Framework\Filesystem\Io\File $fileIo,
        \Magento\Store\Model\StoreManagerInterface $storeManager
    ){
        parent::__construct($context);
        $this->imageUploader = $imageUploader;
        $this->filesystem = $filesystem;
        $this->fileIo = $fileIo;
        $this->storeManager = $storeManager;
    }

    /**
     * Upload file controller action.
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $imageUploadId = $this->getRequest()->getParam('param_name', 'logo');
        try {
            $imageResult = $this->imageUploader->saveFileToTmpDir($imageUploadId);
            // Upload image folder wise
            $imageName = $imageResult['name'];
            $firstName = substr($imageName, 0, 1);
            $secondName = substr($imageName, 1, 1);

            $basePath = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath() . 'logo/image/';
            $mediaRootDir = $this->filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath() . 'logo/image/' . $firstName . '/' . $secondName . '/';

            if (!is_dir($mediaRootDir)) {
                $this->fileIo->mkdir($mediaRootDir, 0775);
            }
            // Set image name with new name, If image already exist
            $newImageName = $this->updateImageName($mediaRootDir, $imageName);
            $this->fileIo->mv($basePath . $imageName, $mediaRootDir . $newImageName);

            // Upload image folder wise
            $imageResult['cookie'] = [
                'name' => $this->_getSession()->getName(),
                'value' => $this->_getSession()->getSessionId(),
                'lifetime' => $this->_getSession()->getCookieLifetime(),
                'path' => $this->_getSession()->getCookiePath(),
                'domain' => $this->_getSession()->getCookieDomain(),
            ];
            $mediaUrl = $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
            $imageResult['name'] = $newImageName;
            $imageResult['file'] = $newImageName;
            $imageResult['url'] = $mediaUrl . 'logo/image/' . $firstName . '/' . $secondName . '/' . $newImageName;
        } catch (\Exception $e) {
            $imageResult = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }
        return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($imageResult);
    }
   
    public function updateImageName($path, $file_name)
    {
        if ($position = strrpos($file_name, '.')) {
            $name = substr($file_name, 0, $position);
            $extension = substr($file_name, $position);
        } else {
            $name = $file_name;
        }
        $new_file_path = $path . '/' . $file_name;
        $new_file_name = $file_name;
        $count = 0;
        while (file_exists($new_file_path)) {
            $new_file_name = $name . '_' . $count . $extension;
            $new_file_path = $path . '/' . $new_file_name;
            $count++;
        }
        return $new_file_name;
    }
}

5) In Last, Update code in your DataProvider.php File to display image after save records :

<?php
/**
 * Created By : Rohan Hapani
 */
namespace RH\Helloworld\Ui\Component\Form\Helloworld;

use Magento\Store\Model\StoreManagerInterface;
use RH\Helloworld\Model\ResourceModel\Helloworld\Collection;
use Magento\Framework\App\RequestInterface;

class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
    /**
     * @var Collection
     */
    protected $collection;

    /**
     * @var array
     */
    protected $loadedData;

    /**
     * @var RequestInterface
     */
    protected $request;

    /**
     * @var StoreManagerInterface
     */
    protected $storeManager;


    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        Collection $collection,
        RequestInterface $request,
        StoreManagerInterface $storeManager,
        array $meta = [],
        array $data = []
    ) {
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
        $this->collection = $collection;
        $this->request = $request;
        $this->storeManager = $storeManager;
    }

    /**
     * Get data
     *
     * @return array
     */
    public function getData()
    {
        if (!$this->loadedData) {
            $storeId = (int) $this->request->getParam('store');
            $this->collection->setStoreId($storeId)->addAttributeToSelect('*');
            $items = $this->collection->getItems();
            foreach ($items as $item) {
                $item->setStoreId($storeId);
                $itemData = $item->getData();
                if (isset($itemData['logo'])) {
                    $imageName = explode('/', $itemData['logo']);
                    $itemData['logo'] = [
                        [
                            'name' => $imageName[3],
                            'url' => $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'logo/image' . $itemData['logo'],
                        ],
                    ];
                } else {
                    $itemData['logo'] = null;
                }
                
                $this->loadedData[$item->getEntityId()] = $itemData;
                break;
            }
        }
        return $this->loadedData;
    }
}

Now, Just execute this below commands and you can see image uploader in your UI form :

php bin/magento s:up
php bin/magento s:s:d -f
php bin/magento c:c

That’s it !!!

I hope this blog is easy to understand about how to upload image using UI component in Magento 2. In case, I missed anything or need to add some information, always feel free to leave a comment in this blog, I’ll get back with proper solution.

Keep liking and sharing 🙂

 

Tagged ,