15

In Magento 2 there's a single image uploader look like this:

enter image description here

it uploads the image using AJAX and will return JSON serialized containing the uploaded image information. Is there a way to recreate this functionality in frontend phtml file?

1
  • I haven't tried this but you can check admin module for the same to get the idea of implementation in front end. – Jarnail S May 14 '18 at 13:25
4

You can create a custom extension (let custom extension name is "Vendor_MyModule") for Front-end image uploading.

I assume you already created the custom extension "Vendor_MyModule". So I am describing here only the necessary files related to image uploading operation.

Please follow below steps .

step 1: Create the uploader model file. app/code/Vendor/MyMocule/Model/Upload/ImageFileUploader.php

File : ImageFileUploader.php

<?php
namespace  Vendor\MyModule\Model\Upload;

use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\MediaStorage\Model\File\UploaderFactory;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\UrlInterface;
use Magento\Store\Model\StoreManagerInterface;

/**
 * Class ImageFileUploader
 * @package Aheadworks\Rbslider\Model\Slide
 */
class ImageFileUploader
{
    /**
     * @var UploaderFactory
     */
    private $uploaderFactory;

    /**
     * @var Filesystem
     */
    private $filesystem;

    /**
     * @var StoreManagerInterface
     */
    private $storeManager;

    /**
     * @var string
     */
    const FILE_DIR = 'vendor_mymodule/uplaods';

    /**
     * @param UploaderFactory $uploaderFactory
     * @param Filesystem $filesystem
     * @param StoreManagerInterface $storeManager
     */
    public function __construct(
        UploaderFactory $uploaderFactory,
        Filesystem $filesystem,
        StoreManagerInterface $storeManager
    ) {
        $this->uploaderFactory = $uploaderFactory;
        $this->storeManager = $storeManager;
        $this->filesystem = $filesystem;
    }

    /**
     * Save file to temp media directory
     *
     * @param string $fileId
     * @return array
     * @throws LocalizedException
     */
    public function saveImageToMediaFolder($fileId)
    {
        try {
            $result = ['file' => '', 'size' => ''];
            /** @var \Magento\Framework\Filesystem\Directory\Read $mediaDirectory */
            $mediaDirectory = $this->filesystem
                ->getDirectoryRead(DirectoryList::MEDIA)
                ->getAbsolutePath(self::FILE_DIR);
            /** @var \Magento\MediaStorage\Model\File\Uploader $uploader */
            $uploader = $this->uploaderFactory->create(['fileId' => $fileId]);
            $uploader->setAllowRenameFiles(true);
            $uploader->setFilesDispersion(false);
            $uploader->setAllowedExtensions($this->getAllowedExtensions());
            $result = array_intersect_key($uploader->save($mediaDirectory), $result);

            $result['url'] = $this->getMediaUrl($result['file']);
        } catch (\Exception $e) {
            $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }
        return $result;
    }

    /**
     * Get file url
     *
     * @param string $file
     * @return string
     */
    public function getMediaUrl($file)
    {
        $file = ltrim(str_replace('\\', '/', $file), '/');
        return $this->storeManager
            ->getStore()
            ->getBaseUrl(UrlInterface::URL_TYPE_MEDIA) . self::FILE_DIR . '/' . $file;
    }

    /**
     * Get allowed file extensions
     *
     * @return string[]
     */
    public function getAllowedExtensions()
    {
        return ['jpg', 'jpeg', 'gif', 'png'];
    }
}

Step 2: Create the Controller to upload the image using the Model created in setp 1

/app/code/Vendor/MyModule/Controller/Index/UploadImage.php

File: UploadImage.php

<?php
    
    namespace  Vendor\MyModule\Controller\Index;
    
    
    use Magento\Framework\App\Action\Action;
    use Magento\Framework\App\Action\Context;
    use Magento\Framework\Controller\ResultFactory;
    use Vendor\MyModule\Model\Upload\ImageFileUploader;
    
    class UploadImage extends \Magento\Framework\App\Action\Action
    {
        
         
        /**
         * @var ImageFileUploader
         */
        private $imageFileUploader;
        
        /**
        * @var \Magento\Store\Model\StoreManagerInterface
        */
        protected $storeManager;
        
    
        /**
         * @param Context $context
         * @param ImageFileUploader $imageFileUploader
         */
        public function __construct(
            Context $context,
            \Magento\Store\Model\StoreManagerInterface $storeManager,
            ImageFileUploader $imageFileUploader
            
        ) {
            $this->storeManager        = $storeManager;       
            $this->imageFileUploader = $imageFileUploader;
            parent::__construct($context);
            
        }
    
        /**
         * Image upload action
         *
         * @return \Magento\Framework\Controller\ResultInterface
         */
        public function execute()
        {        
            $result = $this->imageFileUploader->saveImageToMediaFolder('myimgaeupload');
            return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
        }
    }
        
    

step 3: Create another controller to load the layout app/code/Vendor/MuModule/Controller/Index/Index.php

File : Index.php

<?php
    
    namespace Vendor\MyModule\Controller\Index;
    
    
    class Index extends \Magento\Framework\App\Action\Action
    {
        protected $_pageFactory;
    
        public function __construct(
            \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $pageFactory)
            {
            $this->_pageFactory = $pageFactory;
             return parent::__construct($context);
        }
    
        public function execute()
        {
         

   
       
        $resultPage = $this->_pageFactory->create(); 
       return $resultPage; 
    }
}
   

step 4: Declare routers for your font-end controller. app/code/Vendor/MyModule/etc/frontend/routes.xml

File : routes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="*myupload*" frontName="*myupload*">
            <module name="Vendor_MyModule" />
        </route>
    </router>
</config>

step 5: Declare layout.xml /app/code/Vendor/MyModule//view/frontend/layout/myupload_index_index.xml

File : myupload_index_index.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">             
             <block class="Vendor\MyModule\Block\Myblock" name="myupload_index_index" template="Vendor_MyModule::form.phtml" />
        </referenceContainer>       
    </body>
</page>

step 6: Create the block class file /app/code/Vendor/MyModule/Block/Myblock.php

File : Myblock.php

<?php

namespace Vendor\MyModule\Block;


class Myblock  extends \Magento\Framework\View\Element\Template
{
    
    
}

step 7: create phtml file

/app/code/Vendor/MyModule/view/frontend/templates/form.phtml

File : form.phtml

<h2>Welcome to Ny Image Uploader</h2>
<div class="upload-wrapper" data-bind="scope: 'uploader'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>


<script type="text/x-magento-init">
{
   ".upload-wrapper": {
       "Magento_Ui/js/core/app": {
           "components": {
               "uploader": {                   
                   "component":"Magento_Ui/js/form/element/file-uploader",                   
                   "template": "ui/form/element/uploader/uploader",                   
                   "previewTmpl":"Vendor_MyModule/image-preview",
                   "dataScope" : "myimgaeupload",
                   "uploaderConfig": {
                        "url": "<?php echo $block->getUrl('myupload/index/uploadimage'); ?>"
                   }
               }
           }
       }
   }
}

</script> 

step 8: create KO template file for image preview app/code/Vendor/MyModule/view/frontend/web/template/image-preview.html

File : 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>

step 9) Run following CLI commands

sudo php bin/magento setup:di:compile
sudo rm -rf pub/static/frontend/*
sydo php bin/magento cache:flush

enter image description here

1
  • Is there a way to include this in a form? – Brandon Irwin Dec 30 '20 at 19:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.