Menu Close

    Create Product File Type Attribute in Magento 2

    Create Product File Type Attribute in Magento 2: – In this blog we are going to create and manage product file type attribute in magento 2.

    Follow the below steps in order to create file type attribute:

    Step 1:

    First of all we have to create a product attribute with input type “File”. Here I’m creating it by installer. So, create a InstallData.php file in /app/code/Vendor/Module/Setup directory and copy below code.

    <?php
    namespace Vendor\Module\Setup;
    
    use Magento\Eav\Setup\EavSetupFactory;
    use Magento\Framework\Setup\InstallDataInterface;
    use Magento\Framework\Setup\ModuleContextInterface;
    use Magento\Framework\Setup\ModuleDataSetupInterface;
    use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet;
    use Magento\Catalog\Model\ResourceModel\Product as ResourceProduct;
    
    class InstallData implements InstallDataInterface
    {
        protected $_attributeSet;
        protected $_eavSetupFactory;
        protected $_resourceProduct;
     
        public function __construct(
            AttributeSet $attributeSet,
            EavSetupFactory $eavSetupFactory,
            ResourceProduct $resourceProduct
        ) {
            $this->_attributeSet    = $attributeSet;
            $this->_eavSetupFactory = $eavSetupFactory;
            $this->_resourceProduct = $resourceProduct;
        }
    
        public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) {
            $eavSetup = $this->_eavSetupFactory->create(["setup"=>$setup]);
            $eavSetup->addAttribute(
                \Magento\Catalog\Model\Product::ENTITY,
                'agreement_file',
                [
                    'type' => 'varchar',
                    'label' => 'Agreement File',
                    'input' => 'file',
                    'backend' => 'Vendor\Module\Model\Product\Attribute\Backend\File',
                    'frontend' => '',
                    'class' => '',
                    'source' => '',
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
                    'visible' => true,
                    'required' => false,
                    'user_defined' => true,
                    'default' => '',
                    'searchable' => false,
                    'filterable' => false,
                    'comparable' => false,
                    'visible_on_front' => false,
                    'unique' => false,
                    'apply_to' => 'simple,configurable', // applicable for simple and configurable product 
                    'used_in_product_listing' => false
                ]
            );
    
            // assign attribute to attribute set
            $entityType = $this->_resourceProduct->getEntityType();
            $attributeSetCollection = $this->_attributeSet->setEntityTypeFilter($entityType);
            foreach ($attributeSetCollection as $attributeSet) {
                $eavSetup->addAttributeToSet("catalog_product", $attributeSet->getAttributeSetName(), "General", "agreement_file");
            }
        }
    }

    Step 2:

    Searching for an experienced
    Magento 2 Company ?
    Read More

    Then create backend model File.php(which we have defined in attribute options) in app/code/Vendor/Module/Model/Product/Attribute/Backend directory and copy below code.

    <?php
    namespace Vendor\Module\Model\Product\Attribute\Backend;
    
    use Magento\Framework\App\Filesystem\DirectoryList;
    
    class File extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
    {
        /**
         * @var \Magento\Framework\Filesystem\Driver\File
         */
        protected $_file;
    
        /**
         * @var \Psr\Log\LoggerInterface
         */
        protected $_logger;
    
        /**
         * @var \Magento\Framework\Filesystem
         */
        protected $_filesystem;
    
        /**
         * @var \Magento\MediaStorage\Model\File\UploaderFactory
         */
        protected $_fileUploaderFactory;
        
    
        /**
         * Construct
         *
         * @param \Psr\Log\LoggerInterface $logger
         * @param \Magento\Framework\Filesystem $filesystem
         * @param \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
         */
        public function __construct(
            \Psr\Log\LoggerInterface $logger,
            \Magento\Framework\Filesystem $filesystem,
            \Magento\Framework\Filesystem\Driver\File $file,
            \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
        ) {
            $this->_file = $file;
            $this->_filesystem = $filesystem;
            $this->_fileUploaderFactory = $fileUploaderFactory;
            $this->_logger = $logger;
        }
    
        public function afterSave($object)
        {
            $path = $this->_filesystem->getDirectoryRead(
                DirectoryList::MEDIA
            )->getAbsolutePath(
                'catalog/product/file/'
            );
            $delete = $object->getData($this->getAttribute()->getName() . '_delete');
    
            if ($delete) {
                $fileName = $object->getData($this->getAttribute()->getName());
                $object->setData($this->getAttribute()->getName(), '');
                $this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName());
                if ($this->_file->isExists($path.$fileName))  {
                    $this->_file->deleteFile($path.$fileName);
                }
            }
    
            if (empty($_FILES)) {
                return $this;// if no image is set then nothing to do
            }
    
            try {
                /** @var $uploader \Magento\MediaStorage\Model\File\Uploader */
                $uploader = $this->_fileUploaderFactory->create(['fileId' => 'product['.$this->getAttribute()->getName().']']);
                $uploader->setAllowedExtensions(['pdf']);
                $uploader->setAllowRenameFiles(true);
                $result = $uploader->save($path);
                $object->setData($this->getAttribute()->getName(), $result['file']);
                $this->getAttribute()->getEntity()->saveAttribute($object, $this->getAttribute()->getName());
            } catch (\Exception $e) {
                if ($e->getCode() != \Magento\MediaStorage\Model\File\Uploader::TMP_NAME_EMPTY) {
                    $this->_logger->critical($e);
                }
            }
            
            return $this;
        }
    }

    Step 3:

    To display saved file, we need to define template for the attribute. So, first define modifier class of the attribute in app/code/Vendor/Module/etc/adminhtml/di.xml as mentioned below

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool">
            <arguments>
                <argument name="modifiers" xsi:type="array">
                    <item name="agreement_file" xsi:type="array">
                        <item name="class" xsi:type="string">Vendor\Module\Ui\DataProvider\Product\Form\Modifier\File</item>
                        <item name="sortOrder" xsi:type="number">10</item>
                    </item>
                </argument>
            </arguments>
        </virtualType>
    </config>

     

    Step 4:

    Create modifier class File.php in app/code/Vendor/Module/Ui/DataProvider/Product/Form/Modifier directory and copy below code

    <?php
    namespace Vendor\Module\Ui\DataProvider\Product\Form\Modifier;
    
    use Magento\Framework\Stdlib\ArrayManager;
    use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
    
    class File extends AbstractModifier
    {
        /**
         * @var Magento\Framework\Stdlib\ArrayManager
         */
        protected $arrayManager;
    
        /**
         * @param ArrayManager                $arrayManager
         */
        public function __construct(
            ArrayManager $arrayManager
        ) {
            $this->arrayManager = $arrayManager;
        }
    
        public function modifyMeta(array $meta)
        {
            $fieldCode = 'agreement_file';
            $elementPath = $this->arrayManager->findPath($fieldCode, $meta, null, 'children');
            $containerPath = $this->arrayManager->findPath(static::CONTAINER_PREFIX . $fieldCode, $meta, null, 'children');
    
            if (!$elementPath) {
                return $meta;
            }
    
            $meta = $this->arrayManager->merge(
                $containerPath,
                $meta,
                [
                    'children'  => [
                        $fieldCode => [
                            'arguments' => [
                                'data' => [
                                    'config' => [
                                        'elementTmpl'   => 'Vendor_Module/elements/file',
                                    ],
                                ],
                            ],
                        ]
                    ]
                ]
            );
            return $meta;
        }
    
        /**
         * {@inheritdoc}
         */
        public function modifyData(array $data)
        {
            return $data;
        }
    }

    Step 5:

    At last create template file file.html in /app/code/Vendor/Module/view/adminhtml/web/template/elements directory and write below code

    <input class="admin__control-file" type="file" data-bind="
        hasFocus: focused,
        attr: {
            name: inputName,
            placeholder: placeholder,
            'aria-describedby': noticeId,
            id: uid,
            disabled: disabled,
            form: formId
        }"
    />
    <!-- ko if: $parent.source.data.product[code] -->
    <span>
        <a attr="href: '/pub/media/catalog/product/file/'+$parent.source.data.product[code]" text="$parent.source.data.product[code]"></a>
        <label attr="for: uid+'_delete'">
            <input type="checkbox" attr="name: 'product['+code + '_delete]', id: uid+'_delete', form: formId">
            <span data-bind="i18n:'Delete'"></span>
        </label>
    </span>
    <!-- /ko -->

    In this way we can create file type product attribute in magento 2. Thanks.. 🙂

    For complete module please find at https://github.com/rani-webkul/product-file-attribute.

    . . .
    Discuss on Helpdesk

    Leave a Comment

    Your email address will not be published. Required fields are marked*


    29 comments

  • Amit
    Working in Magento 2.3.2
  • Mohit Gohel
    Hi, I have installed this module for this GitHub link for Succesful this
    the module is installed but I face some issue like when the file is upload
    then for this but when I save but can’t save this file in product And can’t
    showing delete option for this module so give me a suggestion for that How can i sorted. Thanks
    • Rani Priya (Moderator)
      Seems you haven’t installed module properly.
      Please execute below commands and then check
      Php bin/magento setup:upgrade
      Php bin/magento setup:di:compile
      Php bin/magento setup:static-content:deploy
      Php bin/magento cache:clean
  • Prashant Marathe
    I have not used it but one question –
    If I have “n” number of attachments – Maybe 4,5,6 (don’t know exactly) with add more functionality then will it work ?
    • Rani Priya (Moderator)
      Could you explain how you have added add more functionality?
  • Sephora Birmingham
    i have added two attributes and this will shows delete checkbox only for first attribute and second attribute is not shown. can you help me for this.
    • Rani Priya (Moderator)
      Do you have added element template for that attribute in modifyMeta method of class app/code/Vendor/Module/Ui/DataProvider/Product/Form/Modifier/File ?
  • Mikoto
    Hi Mate, thanks for the module, working pretty fine. Just one question, how would you display this attribute in front-office then? Like a downloadable file.

    Thank you so much for your work!

  • duong
    hello, delete button doesnt display
    • Sanjay
      Hi Duong,

      Did you manage to show the delete button?
      I’m facing the same issue

  • Paul Donnelly
    It seems to be using this file
    vendor/magento/module-ui/view/base/web/templates/form/element/media.html
    instead of the modules file
    view/adminhtml/web/template/elements/file.html

    Any reasons why?

  • Paul
    Hi I’ve install your module on 2.2.6, the file has uploaded but the delete option doesnt appear. I can see the file in the correct folder. Any ideas why the delete option isnt appearing?
  • admindev
    not working in magento 2.3.0
  • Hardik Makwana\
    This code is not working into magento 2.3.0 it is nice working into magento 2.2.6
  • Hardik Makwana
    Hello Uploaded file name is not display after Uploading the file also the delete checkbox is not display
    • Rani Priya (Moderator)
      please provide your test instance so that I can look into the issue.
      • Hardik Makwana\
        This code is not working into magento 2.3.0 it is nice working into magento 2.2.6
    • duong
      i got same issue
  • dev
    It is not replacing the file if there is already added file of the product.
  • Ajay
    agreement file is still shown in admin panel even after disabling the module !!
    • Rani Priya (Moderator)
      Please unassign that attribute from attribute set then it will not show.

      To unassign navigate to magento admin panel->Stores->Attributes->Attribute Set
      then edit attribute set and then drag that attribute and drop to Unassigned Attributes.

      Hope it will solve your problem.

  • Ajay
    why Agreement File is showing even after disabling the module!!
    • Rani Priya (Moderator)
      Please unassign that attribute from attribute set then it will not show.
      To unassign navigate to magento admin panel->Stores->Attributes->Attribute Set
      then edit attribute set and then drag that attribute and drop to Unassigned Attributes.

      Hope it will solve your problem.

  • gaurav mishra
    this is not working i followed steps using magento 2.2.6
    • Rani Priya (Moderator)
      Hi Gaurav,

      I have implemented it on the magento 2.2.6 version and It’s working fine.
      Can you please share your code so that I can debug the issue.

    • Senthil
      Yep, this is not working
      • Rani Priya (Moderator)
        For complete module please find at https://github.com/rani-webkul/product-file-attribute. It’s working fine with magento 2.2.6 as well.
        • Senthil
          I install the module from GIT in Magento 2.2.3 and it is not working.
          • Rani Priya (Moderator)
            I have retested it on magento 2.2.3 and magento 2.2.6 version and it’s working fine.

            Can you please explain that what issue you are facing so that I can look into that.

  • Back to Top