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_mapconst 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_mapphp 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.
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.
- Magento 2 Add Image on Admin UI Grid
- Magento 2 Add Customer Fullname on Admin Grid
- How to Add Image Uploader on Store Configuration in Magento 2
- How to Add Custom Select/MultiSelect Options on Store Configuration in Magento 2
- How to Add Dynamic Row on Store Configuration in Magento 2
- How to Add Date & time Picker on Store Configuration in Magento 2
- How to Add Link on Store Configuration Fields Comment in Magento 2
- How to Use Javascript Mixins in Magento 2
- How to Add Custom Validation Rule in Magento 2
- How to Get Product Collection
- How to Setup Magento 2 PWA Studio
- How to Get Current Category
- How to Get Current Product
- Get Product Collection with Filters
- How to Create And Use Plugin In Magento 2