I'm trying to add a simple image upload field to my form in Magento 2, but things are not looking that simple. I'm using UIComponent for the layout, my component is as follows:
<fieldset name="slide">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Add a new Slide</item>
</item>
</argument>
<field name="name">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string">Name</item>
<item name="visible" xsi:type="boolean">true</item>
<item name="dataType" xsi:type="string">text</item>
<item name="formElement" xsi:type="string">input</item>
<item name="source" xsi:type="string">name</item>
</item>
</argument>
</field>
<field name="image">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Slide Image</item>
<item name="formElement" xsi:type="string">fileUploader</item>
<item name="componentType" xsi:type="string">fileUploader</item>
<item name="maxFileSize" xsi:type="number">2097152</item>
<item name="allowedExtensions" xsi:type="string">jpg jpeg gif png svg</item>
<item name="uploaderConfig" xsi:type="array">
<item name="url" xsi:type="string">appfactory/slides/uploadimage</item>
</item>
</item>
</argument>
</field>
</fieldset>
Looking good.
I created a controller to handle the image upload as well:
<?php
namespace AppFactory\Basic\Controller\Adminhtml\Slides;
use Magento\Backend\App\Action;
class Uploadimage extends \Magento\Backend\App\Action
{
protected $_mediaDirectory;
protected $_fileUploaderFactory;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Filesystem $filesystem,
\Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
) {
$this->_mediaDirectory = $filesystem->getDirectoryWrite(
\Magento\Framework\App\Filesystem\DirectoryList::MEDIA
);
$this->_fileUploaderFactory = $fileUploaderFactory;
parent::__construct($context);
}
public function execute()
{
/** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultRedirectFactory->create();
try{
$target = $this->_mediaDirectory->getAbsolutePath('appfactory/slides/');
/** @var $uploader \Magento\MediaStorage\Model\File\Uploader */
$uploader = $this->_fileUploaderFactory->create(['fileId' => 'slide[image]']);
/** Allowed extension types */
$uploader->setAllowedExtensions(['jpg', 'jpeg', 'gif', 'png', 'zip', 'doc']);
/** rename file name if already exists */
$uploader->setAllowRenameFiles(true);
/** upload file in folder "mycustomfolder" */
$result = $uploader->save($target);
if ($result['file']) {
$this->messageManager->addSuccess(__('File has been successfully uploaded'));
}
} catch (\Exception $e) {
$this->messageManager->addError($e->getMessage());
}
return $this->resultRedirectFactory->create()->setPath(
'*/*/uploadimage', ['_secure'=>$this->getRequest()->isSecure()]
);
}
}
I have 2 problems right now,
- The first one is that the upload controller is executed whenever I select the image, not whenever I save the form. Not sure why this is happening, I would like to have it saved only when I save the form.
- The second problem is I don't know what to return from the upload controller after the image is saved (in case it's saved when being selected). I mean when I actually save the form, and the form save controller is called, how should I get the image filename to save it in the database. Solving the first problem would make the second problem irrelevant.