Magento 2 Add Image Uploader on Admin UI Form

In this article, we'll discuss how to add the UI Component image uploader field on the admin form in Magento 2. With the help of this image uploader, you can pick existing images from the gallery and reuse them.

We'll do the following things in this article.

  • Add Image Uploader field on ui form xml file.
  • Create controller for image uploader.
  • Create Image uploader class.
  • Get Save image using dataprovider.

Let's get started!!

Step 1: Add the below on your ui form xml file.

saveCopyzoom_out_map
<field name="image_field">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="dataType" xsi:type="string">string</item>
            <item name="label" xsi:type="string" translate="true">Your Image Field</item>
            <item name="visible" xsi:type="boolean">true</item>
            <item name="allowedExtensions" xsi:type="string">jpg jpeg png</item>
            <item name="maxFileSize" xsi:type="number">2097152</item>
            <item name="formElement" xsi:type="string">imageUploader</item>
            <item name="previewTmpl" xsi:type="string">Magento_Catalog/image-preview</item>
            <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
            <item name="dataScope" xsi:type="string">image_field</item>
            <item name="sortOrder" xsi:type="number">40</item>
            <item name="uploaderConfig" xsi:type="array">
                <item name="url" xsi:type="url" path="helloworld/index/upload">
                    <param name="target_element_id">image_field</param>
                    <param name="type">image</param>
                </item>
            </item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="boolean">true</item>
            </item>
        </item>
    </argument>
</field>

In above code you can see, we've used image_field as a field and helloworld/index/upload as an url path. So, you need to change it according to your. Now we need to create upload controller.

Step 2: Create Upload.php at app/code/Vendorname/Helloworld/Controller/Adminhtml/Index/ and paste the below code.

saveCopyzoom_out_map
<?php

namespace Vendorname\Helloworld\Controller\Adminhtml\Index;

use Magento\Framework\Controller\ResultFactory;

class Upload extends \Magento\Backend\App\Action
{

    /**
     * @var \Vendorname\Helloworld\Model\ImageUploader
     */
    public $imageUploader;

    /**
     * Upload constructor.
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Vendorname\Helloworld\Model\ImageUploader $imageUploader
     */
	public function __construct(
		\Magento\Backend\App\Action\Context $context,
		\Vendorname\Helloworld\Model\ImageUploader $imageUploader
	) {
		parent::__construct($context);
		$this->imageUploader = $imageUploader;
	}

    /**
     * @return mixed
     */
	public function _isAllowed() {
		return $this->_authorization->isAllowed('Vendorname_Helloworld::upload');
	}

    /**
     * @return mixed
     */
    public function execute() {
		try {
			$result = $this->imageUploader->saveFileToTmpDir('image_field');
			$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);
	}
}

In the above code you need to change your field name with image_field. Also, we've inject imageUploader class for save image. So, need to create that.

Step 3: Create ImageUploader.php at app/code/Vendorname/Helloworld/Model/ImageUploader.php and paste the below code.

saveCopyzoom_out_map
<?php

namespace Vendorname\Helloworld\Model;

use Exception;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\UrlInterface;

class ImageUploader
{

    const BASE_TMP_PATH = "wysiwyg/helloworld/";
    const BASE_PATH = "wysiwyg/helloworld/";
    const ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png'];

    /**
     * @var string
     */
    public $baseTmpPath;
    /**
     * @var string
     */
    public $basePath;
    /**
     * @var string[]
     */
    public $allowedExtensions;
    /**
     * @var \Magento\MediaStorage\Helper\File\Storage\Database
     */
    private $coreFileStorageDatabase;
    /**
     * @var \Magento\Framework\Filesystem\Directory\WriteInterface
     */
    private $mediaDirectory;
    /**
     * @var \Magento\MediaStorage\Model\File\UploaderFactory
     */
    private $uploaderFactory;
    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    private $storeManager;
    /**
     * @var \Psr\Log\LoggerInterface
     */
    private $logger;

    /**
     * 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
     * @throws \Magento\Framework\Exception\FileSystemException
     */
    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
    ) {
        $this->coreFileStorageDatabase = $coreFileStorageDatabase;
        $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
        $this->uploaderFactory = $uploaderFactory;
        $this->storeManager = $storeManager;
        $this->logger = $logger;
        $this->baseTmpPath = self::BASE_TMP_PATH;
        $this->basePath = self::BASE_PATH;
        $this->allowedExtensions = self::ALLOWED_EXTENSIONS;
    }

    /**
     * @param $imageName
     * @return mixed
     * @throws 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 LocalizedException(
                __('Something went wrong while saving the file(s).')
            );
        }
        return $imageName;
    }

    /**
     * @return string
     */
    public function getBaseTmpPath()
    {
        return $this->baseTmpPath;
    }

    /**
     * @param $baseTmpPath
     */
    public function setBaseTmpPath($baseTmpPath)
    {
        $this->baseTmpPath = $baseTmpPath;
    }

    /**
     * @return string
     */
    public function getBasePath()
    {
        return $this->basePath;
    }

    /**
     * @param $basePath
     */
    public function setBasePath($basePath)
    {
        $this->basePath = $basePath;
    }

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

    /**
     * @param $fileId
     * @return mixed
     * @throws LocalizedException
     * @throws NoSuchEntityException
     */
    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 LocalizedException(
                __('File can not be saved to the destination folder.')
            );
        }

        $result['tmp_name'] = str_replace('\\', '/', $result['tmp_name']);
        $result['path'] = str_replace('\\', '/', $result['path']);
        $result['url'] = $this->storeManager
                ->getStore()
                ->getBaseUrl(
                    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 LocalizedException(
                    __('Something went wrong while saving the file(s).')
                );
            }
        }
        return $result;
    }

    /**
     * @return string[]
     */
    public function getAllowedExtensions()
    {
        return $this->allowedExtensions;
    }

    /**
     * @param $allowedExtensions
     */
    public function setAllowedExtensions($allowedExtensions)
    {
        $this->allowedExtensions = $allowedExtensions;
    }

    public function saveMediaImage($imageName, $imagePath)
    {
        $baseTmpPath = $this->getBaseTmpPath();
        $basePath = $this->getBasePath();
        $baseImagePath = $this->getFilePath($basePath, $imageName);
        $mediaPath = substr($imagePath, 0, strpos($imagePath, "media"));
        $baseTmpImagePath = str_replace($mediaPath . "media/", "", $imagePath);
        if ($baseImagePath == $baseTmpImagePath) {
            return $imageName;
        }
        try {
            $this->mediaDirectory->copyFile(
                $baseTmpImagePath,
                $baseImagePath
            );
        } catch (Exception $e) {
            throw new LocalizedException(
                __('Something went wrong while saving the file(s).')
            );
        }
        return $imageName;
    }
}

You need to change the below code in the above file with your desire path and required file extension.

saveCopyzoom_out_map
const BASE_TMP_PATH = "wysiwyg/helloworld/";
const BASE_PATH = "wysiwyg/helloworld/";
const ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png'];

Step 4: Create Save.php at app/code/Vendorname/Helloworld/Controller/Adminhtml/Index/Save.php and paste the below code.

saveCopyzoom_out_map
<?php

namespace Vendorname\Helloworld\Controller\Adminhtml\Index;

use Vendorname\Helloworld\Model\HelloworldFactory;
use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Vendorname\Helloworld\Model\ImageUploader;
use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\App\Cache\Manager;

/**
 * Class Save
 * @package Vendorname\Helloworld\Controller\Adminhtml\Index
 */
class Save extends \Magento\Backend\App\Action
{

    /**
     * @var PageFactory
     */
    protected $resultPageFactory;

    /**
     * @var HelloworldFactory
     */
    protected $helloworldFactory;

    /**
     * @var ManagerInterface
     */
    protected $_messageManager;
    /**
     * @var TypeListInterface
     */
    protected $cacheManager;

    /**
     * Save constructor.
     * @param Context $context
     * @param PageFactory $resultPageFactory
     * @param HelloworldFactory $helloworldFactory
     * @param ManagerInterface $messageManager
     * @param UrlRewriteFactory $urlRewriteFactory
     * @param StoreRepositoryInterface $storeRepository
     * @param CollectionFactory $collectionFactory
     */
    public function __construct(
        Context $context,
        PageFactory $resultPageFactory,
        HelloworldFactory $helloworldFactory,
        ImageUploader $imageUploaderModel,
        ManagerInterface $messageManager,
        Manager $cacheManager
    )
    {
        parent::__construct($context);
        $this->resultPageFactory = $resultPageFactory;
        $this->helloworldFactory = $helloworldFactory;
        $this->imageUploaderModel = $imageUploaderModel;
        $this->messageManager = $messageManager;
        $this->cacheManager = $cacheManager;
    }

    /**
     * @return mixed
     */
    public function execute()
    {
        try {
            $resultPageFactory = $this->resultRedirectFactory->create();
            $data = $this->getRequest()->getPostValue();
            $model = $this->helloworldFactory->create();
            $model->setData($data);
            $model = $this->imageData($model, $data);
            $model->save();
            $this->messageManager->addSuccessMessage(__("Data Saved Successfully."));
            $buttonData = $this->getRequest()->getParam('back');
            if ($buttonData == 'edit' && $model->getId()) {
                    return $resultPageFactory->setPath('helloworld/index/form', ['id' => $model->getId()]);
            }
			if ($buttonData == 'new') {
			    return $resultPageFactory->setPath('helloworld/index/form');
			}
			if ($buttonData == 'close') {
				$this->_redirect('helloworld/index/index');
			}
		} catch (\Exception $e) {
			$this->_messageManager->addErrorMessage(__($e));
		}
        return $resultPageFactory->setPath('helloworld/index/index');
    }

    /**
     * @param $model
     * @param $data
     * @return mixed
     */
    public function imageData($model, $data)
    {
        if ($model->getId()) {
            $pageData = $this->helloworldFactory->create();
            $pageData->load($model->getId());
            if (isset($data['image_field'][0]['name'])) {
                $imageName1 = $pageData->getThumbnail();
                $imageName2 = $data['image_field'][0]['name'];
                if ($imageName1 != $imageName2) {
                    $imageUrl = $data['image_field'][0]['url'];
                    $imageName = $data['image_field'][0]['name'];
                    $data['image_field'] = $this->imageUploaderModel->saveMediaImage($imageName, $imageUrl);
                } else {
                    $data['image_field'] = $data['image_field'][0]['name'];
                }
            } else {
                $data['image_field'] = '';
            }
        } else {
            if (isset($data['image_field'][0]['name'])) {
                $imageUrl = $data['image_field'][0]['url'];
                $imageName = $data['image_field'][0]['name'];
                $data['image_field'] = $this->imageUploaderModel->saveMediaImage($imageName, $imageUrl);
            }
        }
        $model->setData($data);
        return $model;
    }
}

You need to modify your save controller and add imageData function and call it before save process as per above example.

Now, we need to create/update DataProvider to get image on edit.

Step 5: Create/Update DataProvider.php at app/code/Vendorname/Helloworld/Model/DataProvider.php and paste the below code.

saveCopyzoom_out_map
<?php
namespace Vendorname\Helloworld\Model;

use Vendorname\Helloworld\Model\ResourceModel\Helloworld\CollectionFactory;
use Magento\Store\Model\StoreManagerInterface;

class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{

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

    /**
     * @var $collection
     */
    protected $collection;


    /**
     * DataProvider constructor.
     * @param string $name
     * @param string $primaryFieldName
     * @param string $requestFieldName
     * @param CollectionFactory $collectionFactory
     * @param array $meta
     * @param array $data
     */
    public function __construct(
        $name,
        $primaryFieldName,
        $requestFieldName,
        CollectionFactory $collectionFactory,
        StoreManagerInterface $storeManager,
        array $meta = [],
        array $data = []
    ) {
        $this->collection = $collectionFactory->create();
        $this->storeManager = $storeManager;
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
    }

    /**
     * @return mixed
     */
    public function getData()
    {
        $items = $this->collection->getItems();
        foreach ($items as $model) {
            $this->loadedData[$model->getId()] = $model->getData();
            if ($model->getImageField()) {
                $m['image_field'][0]['name'] = $model->getImageField();
                $m['image_field'][0]['url'] = $this->getMediaUrl($model->getImageField());
                $fullData = $this->loadedData;
                $this->loadedData[$model->getId()] = array_merge($fullData[$model->getId()], $m);
            }
        }
        return $this->loadedData;
    }
    public function getMediaUrl($path = '')
    {
        $mediaUrl = $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'wysiwyg/helloworld/' . $path;
        return $mediaUrl;
    }
}

If you already have DataProvider then update getData function with the above one.

Step 6: Now, open Command line in folder root of magento and run both commands.

saveCopyzoom_out_map
php bin/magento setup:upgrade

php bin/magento cache:flush

That's it,

Now open your ui form and check. You'll see somtnhing like below screenshot.

Magento 2 Add Image Uploader on Admin UI Form

I hope this post helped you to find what you were looking for.

Bookmark it for your future reference. Do comment below if you have any other questions or doubts.

P.S. Do share this post with your team.

Review other articles maybe it'll help you too.




Search
Recent Articles
Tags
Newsletter
Copyright © 2022 devhooks.in All rights reserved.
Ads OFF toggle_off
wifi_off