Magento 2.2 UI Form – Image Field Setup

image-uploadmagento2.2PHPui-form

I need to create a image upload field in my Ui form.

I have created below files.

But while trying to upload an image, it shows a below error.

Please suggest me a solution to save a image in DB.
I got following error
enter image description here

Upload.php

<?php

namespace OX\HomeSlider\Controller\Adminhtml\HomeSlider\Image;

use Magento\Framework\Controller\ResultFactory;

/**
 * Class Upload
 */
class Upload extends \Magento\Backend\App\Action
{

    /**
     * Image uploader
     *
     * @var \Namespace\Module\Model\ImageUploader
     */
    protected $imageUploader;

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

    /**
     * Check admin permissions for this controller
     *
     * @return boolean
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('OX_HomeSlider::HomeSlider');
    }

    /**
     * Upload file controller action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {

        try {
            $result = $this->imageUploader->saveFileToTmpDir('image');

        } catch (\Exception $e) {
            $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }
        return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
    }

}

di.xml

<virtualType name="OXHomeSliderImageUploader" type="Magento\Catalog\Model\ImageUploader">
        <arguments>
            <argument name="baseTmpPath" xsi:type="string">homeslider/tmp</argument>
            <argument name="basePath" xsi:type="string">homeslider</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="OX\HomeSlider\Controller\Adminhtml\HomeSlider\Image\Upload">
        <arguments>
            <argument name="imageUploader" xsi:type="object">OXHomeSliderImageUploader</argument>
        </arguments>
    </type>

ox_homeslider_form.xml

<field name="image" formElement="fileUploader">
            <settings>
                <notice translate="true">Allowed file types: jpeg, gif, png.</notice>
                <label translate="true">Image</label>
                <componentType>fileUploader</componentType>
            </settings>
            <formElements>
                <fileUploader>
                    <settings>
                        <allowedExtensions>jpg jpeg gif png</allowedExtensions>
                        <maxFileSize>2097152</maxFileSize>
                        <uploaderConfig>
                            <param xsi:type="string" name="url">ox_homeslider/homeslider_image/upload</param>
                        </uploaderConfig>
                    </settings>
                </fileUploader>
            </formElements>
        </field>

save.php

namespace OX\HomeSlider\Controller\Adminhtml\Post;

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

    public function __construct(
    \Magento\Backend\App\Action\Context $context, \Magento\Backend\Model\View\Result\RedirectFactory $resultRedirectFactory
    )
    {
        $this->resultRedirectFactory = $resultRedirectFactory;
        parent::__construct($context);
    }

    public function execute()
    {
        $id = $this->getRequest()->getParam('id');
        $postModel = $this->_objectManager->create('OX\HomeSlider\Model\Post');

        if ($id) {
            $postModel = $postModel->load($id);
        }  
        $post = $this->getRequest()->getParams();

        if(empty($post['id'])) {
             $post['id'] = null;
         }
        $postModel->setData($post);
        $postModel->save();
        return $this->resultRedirectFactory->create()->setPath('homeslider/post/index');
        return $result;
    }

}

Best Answer

it is giving error because of this code

<uploaderConfig>
     <param xsi:type="string" name="url">theme/design_config_fileUploader/save</param>
</uploaderConfig>

Reason is the mentioned url theme/design_config_fileUploader/save may not exist or having wrong code.

you can refer category edit form and uploaded action for this, below are the path for files

Category Form

vendor/magento/module-catalog/view/adminhtml/ui_component/category_form.xml

Upload Action

vendor/magento/module-catalog/Controller/Adminhtml/Category/Image/Upload.php

Check this answer to create controller action to upload image

Update:

change url in your above <uploaderConfig> node to below

<uploaderConfig>
     <param xsi:type="string" name="url">namespace_module/module_image/upload</param>
</uploaderConfig>

Create a controller action at path Filename - Upload.php

Namespace\Module\Controller\Adminhtml\Module\Image

In this File add below code

namespace Namespace\Module\Controller\Adminhtml\Module\Image;

use Magento\Framework\Controller\ResultFactory;

/**
 * Class Upload
 */
class Upload extends \Magento\Backend\App\Action
{
    /**
     * Image uploader
     *
     * @var \Namespace\Module\Model\ImageUploader
     */
    protected $imageUploader;

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

    /**
     * Check admin permissions for this controller
     *
     * @return boolean
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Namespace_Module::Module');
    }

    /**
     * Upload file controller action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        try {
            $result = $this->imageUploader->saveFileToTmpDir('image');

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

Add below code to your module's etc/di.xml

<virtualType name="ModuleImageUploader" type="Magento\Catalog\Model\ImageUploader"><!-- replace Module with your entity name -->
    <arguments>
        <argument name="baseTmpPath" xsi:type="string">module/tmp</argument>
        <argument name="basePath" xsi:type="string">module</argument>
        <argument name="allowedExtensions" xsi:type="array"><!-- you can add here file extension restrictions -->
            <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="Namespace\Module\Controller\Adminhtml\Module\Image\Upload">
    <arguments>
        <argument name="imageUploader" xsi:type="object">ModuleImageUploader</argument><!-- again, replace Module with the name of your entity. Make sure it matches the name of the virtual type above. -->
    </arguments>
</type>

Note: Do not forgot to change Namespace and Module to your Namespace and Module name