I am getting an error when I added image uploader to admin html, according to this reference:
https://magento.stackexchange.com/questions/184731/magento-2-implement-ui-fileuploader
However it's getting an error and not uploading an image.
There is no error on log files and no way to see what went wrong.
A technical problem with the server created an error. Try again to continue what you were doing. If the problem persists, try again later.
Do you have any suggestions to fix the error?
Hello tvgarden
You can use below reference to get ui component image upload
Url: https://blog.qaisarsatti.com/magento_2/magento-2-ui-component-image-upload/
hope it will help you, if works then mark as solution.
I have tried the code on the link.
I prompts a popup dialog:
Attention The file was not uploaded.
Hello tvgarden
Please take look, it's used UI fileuploader component in that extension.
https://github.com/mageprince/magento2-FAQ
1) Add field in admin_form.xml(Admin Form)
<field name="icon"> <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">FaqGroup</item> <item name="label" xsi:type="string" translate="true">Group 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">Vendor_Module/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="your_router/faqgroup/upload"/> </item> </item> </argument> </field>
Now we need to create controller which we define in uploaderConfig in admin form: <item name="url" xsi:type="url" path="vendor_module/faqgroup/upload"/>
app/code/Vendor/Module/Controller/Adminhtml/FaqGroup/Upload.php
namespace Vendor\Module\Controller\Adminhtml\FaqGroup; use Magento\Framework\Controller\ResultFactory; class Upload extends \Magento\Backend\App\Action { public $imageUploader; public function __construct( \Magento\Backend\App\Action\Context $context, \Vendor\Module\Model\ImageUploader $imageUploader ) { parent::__construct($context); $this->imageUploader = $imageUploader; } public function _isAllowed() { return $this->_authorization->isAllowed('Vendor_Module::Faq'); } public function execute() { try { $result = $this->imageUploader->saveFileToTmpDir('icon'); $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); } }
3) Create ImageUploader.php
app/code/Vendor/Module/Model/ImageUploader.php
<?php namespace Prince\Faq\Model; class ImageUploader { private $coreFileStorageDatabase; private $mediaDirectory; private $uploaderFactory; private $storeManager; private $logger; public $baseTmpPath; public $basePath; public $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 ) { $this->coreFileStorageDatabase = $coreFileStorageDatabase; $this->mediaDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA); $this->uploaderFactory = $uploaderFactory; $this->storeManager = $storeManager; $this->logger = $logger; $this->baseTmpPath = "faq/tmp/icon"; $this->basePath = "faq/icon"; $this->allowedExtensions= ['jpg', 'jpeg', 'gif', 'png']; } public function setBaseTmpPath($baseTmpPath) { $this->baseTmpPath = $baseTmpPath; } public function setBasePath($basePath) { $this->basePath = $basePath; } public function setAllowedExtensions($allowedExtensions) { $this->allowedExtensions = $allowedExtensions; } public function getBaseTmpPath() { return $this->baseTmpPath; } public function getBasePath() { return $this->basePath; } public function getAllowedExtensions() { return $this->allowedExtensions; } public function getFilePath($path, $imageName) { return rtrim($path, '/') . '/' . ltrim($imageName, '/'); } 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; } 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.') ); } $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; } }
4) Create image-preview.html
app/code/Vendor/Module/view/adminhtml/web/template/image-preview.html
<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>
5) Now add arguments for ImageUploader.php in di.xml
app/code/Vendor/Module/etc/di.xml
<type name="Vendor\Module\Model\ImageUploader"> <arguments> <!-- Temporary file stored in pub/media/faq/tmp/icon --> <argument name="baseTmpPath" xsi:type="string">faq/tmp/icon</argument> <argument name="basePath" xsi:type="string">faq/icon</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> </type>
To save image in database
app/code/Vendor/Module/Controller/Adminhtml/Save.php
<?php namespace Vendor\Module\Controller\Adminhtml; use Magento\Framework\Exception\LocalizedException; class Save extends \Magento\Backend\App\Action { protected $dataPersistor; public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Framework\App\Request\DataPersistorInterface $dataPersistor ) { $this->dataPersistor = $dataPersistor; parent::__construct($context); } public function execute() { ... ... $data = $this->_filterFoodData($data); $model->setData($data); $model->save(); ... ... } public function _filterFoodData(array $rawData) { //Replace icon with fileuploader field name $data = $rawData; if (isset($data['icon'][0]['name'])) { $data['icon'] = $data['icon'][0]['name']; } else { $data['icon'] = null; } return $data; } }
To show uploaded image in form edit page:
app/code/Vendor/Module/Model/DataProvider.php
<?php namespace Vendor\Module\Model; use Magento\Store\Model\StoreManagerInterface; class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider { ... ... public function getData() { ... ... $items = $this->collection->getItems(); //Replace icon with fileuploader field name foreach ($items as $model) { $this->loadedData[$model->getId()] = $model->getData(); if ($model->getIcon()) { $m['icon'][0]['name'] = $model->getIcon(); $m['icon'][0]['url'] = $this->getMediaUrl().$model->getIcon(); $fullData = $this->loadedData; $this->loadedData[$model->getId()] = array_merge($fullData[$model->getId()], $m); } } ... ... return $this->loadedData; } public function getMediaUrl() { $mediaUrl = $this->storeManager->getStore() ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA).'faq/tmp/icon/'; return $mediaUrl; } }
Hi @prakash786
Thanks for your reply.
I have done it as you suggested, it's getting the same issue.
I am using my own module and I have to make the file name to 'image' and there is no folder for "FaqGroup", so I copied Upload.php to Controller/Adminhtml.
I wonder what comes at the end of this path in Upload.php
public function _isAllowed() { return $this->_authorization->isAllowed('Vendor_Module::??????'); }
Also what comes in "source" and "url" in di.xml
<field name="image"> <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">???</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">Vendor_Module/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="???/index/upload"/> </item> </item> </argument> </field>
This is the response from the path/upload/?isAjax=true
------WebKitFormBoundaryKsSjENZLY7DqgkaB Content-Disposition: form-data; name="form_key" BSAWcgWYTzZ00E5n ------WebKitFormBoundaryKsSjENZLY7DqgkaB Content-Disposition: form-data; name="general[image]"; filename="test.jpg" Content-Type: image/jpeg ------WebKitFormBoundaryKsSjENZLY7DqgkaB Content-Disposition: form-data; name="param_name" general[image] ------WebKitFormBoundaryKsSjENZLY7DqgkaB--
I can see only thing is missing is your controller image configuration in di.xml
<type name="QaisarSatti\HelloWorld\Controller\Adminhtml\Index\Upload"> <arguments> <argument name="imageUploader" xsi:type="object">QaisarSatti\HelloWorld\HelloWorldImageUpload</argument> </arguments> </type>
Make sure you set the virtual type for controller too.
... sometimes I wonder,... if after putting all these files in place just to upload a simple image,...
What's the point of using this framework from the first place?
Doesn't (or; Shouldn't) Magento provide "upload image" out of the box as a part of its huge framework?!
I follow same instruction but file upload field name show fieldset array fieldset_name[icon] but file name should be show only icon not ieldset_name[icon]
Please let me know where i am doing mistake.
Thanks
Sanjeev