Magento 2 ui component image upload

Today we discuss how in Magento 2 ui component image upload.This tutorial is include image upload and show image in edit form,ui components tutorial for image upload,create ui component. This tutorial included the custom image upload, custom image unloader and save image in database.

Step 1: Add Ui component image field

<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">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="previewTmpl" xsi:type="string">QaisarSatti_HelloWorld/image-preview</item>
                    <item name="required" xsi:type="boolean">false</item>
                    <item name="uploaderConfig" xsi:type="array">
                        <item name="url" xsi:type="url" path="helloworld/index/upload"/>
                    </item>
                </item>
            </argument>
   </field>

Step 2: Create template file

Create file name image-preview.html in directory.

QaisarSatti/HelloWorld/view/adminhtml/web/template/

<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>

Step 2: Create Image uploader

Create ImageUploader.php in following directory

QaisarSatti\HelloWorld\Model

<?php
/**
* Simple Hello World Module
*
* @category QaisarSatti
* @package QaisarSatti_HelloWorld
* @author Muhammad Qaisar Satti
* @Email qaisarssatti@gmail.com
*
*/

namespace QaisarSatti\HelloWorld\Model;

/**
 * Catalog image uploader
 */

class ImageUploader
{
    /**
     * Core file storage database
     *
     * @var \Magento\MediaStorage\Helper\File\Storage\Database
     */

    protected $coreFileStorageDatabase;

    /**
     * Media directory object (writable).
     *
     * @var \Magento\Framework\Filesystem\Directory\WriteInterface
     */

    protected $mediaDirectory;

    /**
     * Uploader factory
     *
     * @var \Magento\MediaStorage\Model\File\UploaderFactory
     */

    private $uploaderFactory;

    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */

    protected $storeManager;

    /**
     * @var \Psr\Log\LoggerInterface
     */

    protected $logger;

    /**
     * Base tmp path
     *
     * @var string
     */

    protected $baseTmpPath;

    /**
     * Base path
     *
     * @var string
     */

    protected $basePath;

    /**
     * Allowed extensions
     *
     * @var string
     */

    protected $allowedExtensions;

    /**
     * ImageUploader constructor
     *
     * @param \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase
     * @param \Magento\Framework\Filesystem $filesystem
     * @param \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Psr\Log\LoggerInterface $logger
     * @param string $baseTmpPath
     * @param string $basePath
     * @param string[] $allowedExtensions
     */

    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,
        $allowedExtensions
    ) {
        $this->coreFileStorageDatabase = $coreFileStorageDatabase;
        $this->mediaDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
        $this->uploaderFactory = $uploaderFactory;
        $this->storeManager = $storeManager;
        $this->logger = $logger;
        $this->baseTmpPath = $baseTmpPath;
        $this->basePath = $basePath;
        $this->allowedExtensions = $allowedExtensions;
    }

    /**
     * Set base tmp path
     *
     * @param string $baseTmpPath
     *
     * @return void
     */

    public function setBaseTmpPath($baseTmpPath)
    {
        $this->baseTmpPath = $baseTmpPath;
    }

    /**
     * Set base path
     *
     * @param string $basePath
     *
     * @return void
     */

    public function setBasePath($basePath)
    {
        $this->basePath = $basePath;
    }

    /**
     * Set allowed extensions
     *
     * @param string[] $allowedExtensions
     *
     * @return void
     */

    public function setAllowedExtensions($allowedExtensions)
    {
        $this->allowedExtensions = $allowedExtensions;
    }

    /**
     * Retrieve base tmp path
     *
     * @return string
     */

    public function getBaseTmpPath()
    {
        return $this->baseTmpPath;
    }

    /**
     * Retrieve base path
     *
     * @return string
     */

    public function getBasePath()
    {
        return $this->basePath;
    }

    /**
     * Retrieve base path
     *
     * @return string[]
     */

    public function getAllowedExtensions()
    {
        return $this->allowedExtensions;
    }

    /**
     * Retrieve path
     *
     * @param string $path
     * @param string $imageName
     *
     * @return string
     */

    public function getFilePath($path, $imageName)
    {
        return rtrim($path, '/') . '/' . ltrim($imageName, '/');
    }

    /**
     * Checking file for moving and move it
     *
     * @param string $imageName
     *
     * @return string
     *
     * @throws \Magento\Framework\Exception\LocalizedException
     */

    public function moveFileFromTmp($imageName)
    {
        $baseTmpPath = $this->getBaseTmpPath();
        $basePath = $this->getBasePath();

        $baseImagePath = $this->getFilePath($basePath, $imageName);
        $baseTmpImagePath = $this->getFilePath($baseTmpPath, $imageName);

        try {
            $this->coreFileStorageDatabase->copyFile(
                $baseTmpImagePath,
                $baseImagePath
            );
            $this->mediaDirectory->renameFile(
                $baseTmpImagePath,
                $baseImagePath
            );
        } catch (\Exception $e) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('Something went wrong while saving the file(s).')
            );
        }

        return $imageName;
    }

    /**
     * Checking file for save and save it to tmp dir
     *
     * @param string $fileId
     *
     * @return string[]
     *
     * @throws \Magento\Framework\Exception\LocalizedException
     */

    public function saveFileToTmpDir($fileId)
    {
        $baseTmpPath = $this->getBaseTmpPath();

        $uploader = $this->uploaderFactory->create(['fileId' => $fileId]);
        $uploader->setAllowedExtensions($this->getAllowedExtensions());
        $uploader->setAllowRenameFiles(true);

        $result = $uploader->save($this->mediaDirectory->getAbsolutePath($baseTmpPath));

        if (!$result) {
            throw new \Magento\Framework\Exception\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->storeManager
                ->getStore()
                ->getBaseUrl(
                    \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
                ) . $this->getFilePath($baseTmpPath, $result['
file']);
        $result['
name'] = $result['file'];

        if (isset($result['
file'])) {
            try {
                $relativePath = rtrim($baseTmpPath, '
/') . '/' . ltrim($result['file'], '/');
                $this->coreFileStorageDatabase->saveFile($relativePath);
            } catch (\Exception $e) {
                $this->logger->critical($e);
                throw new \Magento\Framework\Exception\LocalizedException(
                    __('
Something went wrong while saving the file(s).')
                );
            }
        }

        return $result;
    }
}

Step 4: Image Configuration

Now add your image configuration in di.xml. These configuration include upload base path and upload base temp path for image upload. Type will be your upload controller.

QaisarSatti\HelloWorld\etc\

Now adding the configuration in di.xml.

<virtualType name="QaisarSatti\HelloWorld\HelloWorldImageUpload" type="QaisarSatti\HelloWorld\Model\ImageUploader">
    <arguments>
            <argument name="baseTmpPath" xsi:type="string">test/tmp</argument>
            <argument name="basePath" xsi:type="string">test</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="QaisarSatti\HelloWorld\Controller\Adminhtml\Index\Upload">
    <arguments>
            <argument name="imageUploader" xsi:type="object">QaisarSatti\HelloWorld\HelloWorldImageUpload</argument>
    </arguments>
</type>

Step 5: Controller Upload Image

<?php
/**
* Simple Hello World Module
*
* @category QaisarSatti
* @package QaisarSatti_HelloWorld
* @author Muhammad Qaisar Satti
* @Email qaisarssatti@gmail.com
*
*/

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

use Magento\Framework\Controller\ResultFactory;

/**
 * Class Upload
 */

class Upload extends \Magento\Backend\App\Action
{
    /**
     * Image uploader
     *
     * @var \Magento\Catalog\Model\ImageUploader
     */

    protected $imageUploader;

    /**
     * Upload constructor.
     *
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Catalog\Model\ImageUploader $imageUploader
     */

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \QaisarSatti\HelloWorld\Model\ImageUploader $imageUploader
    ) {
        parent::__construct($context);
        $this->imageUploader = $imageUploader;
    }

    /**
     * Check admin permissions for this controller
     *
     * @return boolean
     */

    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('QaisarSatti_HelloWorld::helloworld1');
    }

    /**
     * Upload file controller action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */

    public function execute()
    {
        try {
            $result = $this->imageUploader->saveFileToTmpDir('logo');

            $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);
    }
}

Step 5: Controller Save Image

<?php
/**
* Simple Hello World Module
*
* @category QaisarSatti
* @package QaisarSatti_HelloWorld
* @author Muhammad Qaisar Satti
* @Email qaisarssatti@gmail.com
*
*/

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\Exception\LocalizedException;

class Save extends \Magento\Backend\App\Action
{
   
    const ADMIN_RESOURCE = 'QaisarSatti_HelloWorld::helloworld';    
    protected $dataProcessor;    
    protected $dataPersistor;
    protected $imageUploader;


    public function __construct(
        Action\Context $context,
        PostDataProcessor $dataProcessor,
        DataPersistorInterface $dataPersistor
    ) {
        $this->dataProcessor = $dataProcessor;
        $this->dataPersistor = $dataPersistor;
        parent::__construct($context);
    }

    public function execute()
    {
       
        $data = $this->getRequest()->getPostValue();
     

        $resultRedirect = $this->resultRedirectFactory->create();
        if ($data) {



       

            if (isset($data['logo'][0]['name']) && isset($data['logo'][0]['tmp_name'])) {
                $data['image'] =$data['logo'][0]['name'];
                $this->imageUploader = \Magento\Framework\App\ObjectManager::getInstance()->get(
                'QaisarSatti\HelloWorld\HelloWorldImageUpload'
            );
                $this->imageUploader->moveFileFromTmp($data['image']);
            } elseif (isset($data['logo'][0]['image']) && !isset($data['logo'][0]['tmp_name'])) {
                $data['image'] = $data['logo'][0]['image'];
            } else {
                $data['image'] = null;
            }


        return $resultRedirect->setPath('*/*/');
    }
}

Step 5: Edit Form Showing Image

Now we will add data to show image on edit form.For resourceModel reference kindly look into Magento 2 create Custom Model For that you have to provide image ur

In DataProvider

<?php
/**
* Simple Hello World Module
*
* @category QaisarSatti
* @package QaisarSatti_HelloWorld
* @author Muhammad Qaisar Satti
* @Email qaisarssatti@gmail.com
*
*/

namespace QaisarSatti\HelloWorld\Model\HelloWorld;

use QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\CollectionFactory;
use Magento\Framework\App\Request\DataPersistorInterface;

/**
 * Class DataProvider
 */

class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
    /**
     * @var \Magento\Cms\Model\ResourceModel\Block\Collection
     */

    protected $collection;

    /**
     * @var DataPersistorInterface
     */

    protected $dataPersistor;

    /**
     * @var array
     */

    public    $_storeManager;    

    protected $loadedData;

    /**
     * Constructor
     *
     * @param string $name
     * @param string $primaryFieldName
     * @param string $requestFieldName
     * @param CollectionFactory $blockCollectionFactory
     * @param DataPersistorInterface $dataPersistor
     * @param array $meta
     * @param array $data
     */

    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        CollectionFactory $helloworldCollectionFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        DataPersistorInterface $dataPersistor,
        array $meta = [],
        array $data = []
    ) {
        $this->collection = $helloworldCollectionFactory->create();
        $this->dataPersistor = $dataPersistor;
        $this->_storeManager=$storeManager;
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
    }

    /**
     * Get data
     *
     * @return array
     */

    public function getData()
    {
        $baseurl =  $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
        if (isset($this->loadedData)) {
            return $this->loadedData;
        }
        $items = $this->collection->getItems();
        /** @var \Magento\Cms\Model\Block $block */
        foreach ($items as $helloworld) {
             $temp = $helloworld->getData();
             if($temp['image']):
            $img = [];
            $img[0]['image'] = $temp['image'];
            $img[0]['url'] = $baseurl.'test/'.$temp['image'];
            $temp['logo'] = $img;
            endif;
           

        $data = $this->dataPersistor->get('helloworld');
        if (!empty($data)) {
            $helloworld = $this->collection->getNewEmptyItem();
            $helloworld>setData($data);
            $this->loadedData[$helloworld->getLabelId()] = $helloworld->getData();
            $this->dataPersistor->clear('helloworld');
        }else {
            if($items):
            if ($helloworld->getData('image') != null) {

                $t2[$helloworld>getId()] = $temp;    
                 
                return $t2;
            } else {                
                 
           
               return $this->loadedData;
               
            }
            endif;
          }


        return $this->loadedData;
    }
}

Note: You can follow this for multiple image too. Just repeat the process for every Image you want to add.

Qaisar Satti

Hi, I'm Qaisar Satti! I've been a developer for over 20 years, and now I love sharing what I've learned through tutorials and guides. Whether you're working with Magento, PrestaShop, or WooCommerce, my goal is to make your development journey a bit easier and more fun. When I'm not coding or writing, you can find me exploring new tech trends and hanging out with the amazing developer community. Thanks for stopping by, and happy coding!

16 thoughts on “Magento 2 ui component image upload

  1. Hi,
    I’m trying your article to implement in my custom module, but getting exception “Missing required argument $baseTmpPath of QaisarSatti\HelloWorld\Model\ImageUploader.” when upload image.
    Is anything else that’s need to be add in custom module?
    My magento cms version is 2.1.7

    Thanks

  2. Hi,
    The template file directory should be QaisarSatti/HelloWorld/view/adminhtml/web/template/ instead of QaisarSatti/HelloWorld/view/web/template/, Overall the above method worked for me 🙂

  3. Parse error: syntax error, unexpected ‘tmp_name’ (T_STRING), expecting ‘,’ or ‘)’ in /opt/lampp/htdocs/store/app/code/FME/BackgroundImage/Model/ImageUploader.php on line 246

    1. it is because of the tool I am using for code highlight. you can replace to avoid that.

      $result[‘tmp_name’] = str_replace(‘\\’, ‘/’, $result[‘tmp_name’]);

Leave a Reply