You need to create a class to handle your image upload field and show the image once is uploaded.
So create [Namespace]\[Module]\Block\Adminhtml\[Entity]\Helper\Image
class
<?php
namespace [Namespace]\[Module]\Block\Adminhtml\[Entity]\Helper;
use Magento\Framework\Data\Form\Element\Image as ImageField;
use Magento\Framework\Data\Form\Element\Factory as ElementFactory;
use Magento\Framework\Data\Form\Element\CollectionFactory as ElementCollectionFactory;
use Magento\Framework\Escaper;
use [Namespace]\[Module]\Model\[Entity]\Image as [Entity]Image;
use Magento\Framework\UrlInterface;
/**
* @method string getValue()
*/
class Image extends ImageField
{
/**
* image model
*
* @var \[Namespace]\[Module]\Model\[Entity]\Image
*/
protected $imageModel;
/**
* @param [Entity]Image $imageModel
* @param ElementFactory $factoryElement
* @param ElementCollectionFactory $factoryCollection
* @param Escaper $escaper
* @param UrlInterface $urlBuilder
* @param array $data
*/
public function __construct(
[Entity]Image $imageModel,
ElementFactory $factoryElement,
ElementCollectionFactory $factoryCollection,
Escaper $escaper,
UrlInterface $urlBuilder,
$data = []
)
{
$this->imageModel = $imageModel;
parent::__construct($factoryElement, $factoryCollection, $escaper, $urlBuilder, $data);
}
/**
* Get image preview url
*
* @return string
*/
protected function _getUrl()
{
$url = false;
if ($this->getValue()) {
$url = $this->imageModel->getBaseUrl().$this->getValue();
}
return $url;
}
}
then create the class that will help you retrieve the image upload path and upload dir
<?php
namespace [Namespace]\[Module]\Model\[Entity];
use Magento\Framework\UrlInterface;
use Magento\Framework\Filesystem;
use Magento\Framework\App\Filesystem\DirectoryList;
class Image
{
/**
* media sub folder
* @var string
*/
protected $subDir = '[namespace]/[module]/[entity]';
/**
* url builder
*
* @var \Magento\Framework\UrlInterface
*/
protected $urlBuilder;
/**
* @var \Magento\Framework\Filesystem
*/
protected $fileSystem;
/**
* @param UrlInterface $urlBuilder
* @param Filesystem $fileSystem
*/
public function __construct(
UrlInterface $urlBuilder,
Filesystem $fileSystem
)
{
$this->urlBuilder = $urlBuilder;
$this->fileSystem = $fileSystem;
}
/**
* get images base url
*
* @return string
*/
public function getBaseUrl()
{
return $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]).$this->subDir.'/image';
}
/**
* get base image dir
*
* @return string
*/
public function getBaseDir()
{
return $this->fileSystem->getDirectoryWrite(DirectoryList::MEDIA)->getAbsolutePath($this->subDir.'/image');
}
}
now in your edit for tab add this in the method _prepareForm
right after declaring the fieldset
$fieldset->addType('image', '\[Namespace]\[Module]\Adminhtml\[Entity]\Helper\Image');
and add your image field like this
$fieldset->addField(
'image_field_name',
'image',
[
'name' => 'image_field_name',
'label' => __('Image field Label'),
'title' => __('Image field Label'),
]
);
In the controller that saves your entity you need to inject in the constructor the following classes
Magento\MediaStorage\Model\File\UploaderFactory
and [Namespace]\[Module]\Model\[Entity]\Image
So make your class look like this
<?php
class ....
protected $uploaderFactory;
protected $imageModel;
public function __construct(
....
\Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
\[Namespace]\[Module]\Model\[Entity]\Image $imageModel,
....
){
...
$this->uploaderFactory = $uploaderFactory;
$this->imageModel = $imageModel;
...
}
Now, in the same controller add this, before calling $[entity]->save()
$imageName = $this->uploadFileAndGetName('image_field_name', $this->imageModel->getBaseDir(), $data);
$[entity]->setImageFieldName($imageName);
and create this method:
public function uploadFileAndGetName($input, $destinationFolder, $data)
{
try {
if (isset($data[$input]['delete'])) {
return '';
} else {
$uploader = $this->uploaderFactory->create(['fileId' => $input]);
$uploader->setAllowRenameFiles(true);
$uploader->setFilesDispersion(true);
$uploader->setAllowCreateFolders(true);
$result = $uploader->save($destinationFolder);
return $result['file'];
}
} catch (\Exception $e) {
if ($e->getCode() != \Magento\Framework\File\Uploader::TMP_NAME_EMPTY) {
throw new FrameworkException($e->getMessage());
} else {
if (isset($data[$input]['value'])) {
return $data[$input]['value'];
}
}
}
return '';
}
A full example on how to create an entity that supports image and file upload (it's a bit different than described here as it contains an extra class for upload) can be found here