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
<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-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
/**
* 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.
<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
/**
* 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
/**
* 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
/**
* 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.
16 thoughts on “Magento 2 ui component image upload”
Leave a Reply
You must be logged in to post a comment.
i have some this problem https://stackoverflow.com/questions/2670876/magento-file-was-not-uploaded
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
It’s seem like you don’t set path in di.xml
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 🙂
Thanks for correction.
Something I do not see where you created ResourceModel
Thanks for your comment. I added the reference for resourceModel
I run into this problem: Uncaught TypeError: value.map is not a function file-uploader.js:69
Do you know how to solve it?
Kindly check your di.xml. upload url are not using the di.xml virtual type.
can you please provide image upload code to my mail id. Still i am facing issue in edit form
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
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’]);
Into Magento 2.3.0 version this code is not working “Attention: The file was not uploaded.” error occured.
This is not code issue you have required Require php fileinfo extension for uploading.
Hi,
Am getting bellow error in Magento ver. 2.3.1
“Attention
The file was not uploaded.”
This is not code issue you have required Require php fileinfo extension for uploading.