I have a create product attribute
But it’s not save file in pub/media folder
-> VendorModule:- MeetanshiProductAttachment
-> attribute_field_name:- custom_product_attachment
-> Media folder path:- custom/product/attachment
MeetanshiProductAttachmentSetupInstallData.php
<?php
namespace MeetanshiProductAttachmentSetup;
use MagentoFrameworkSetupModuleContextInterface;
use MagentoFrameworkSetupModuleDataSetupInterface;
use MagentoFrameworkSetupInstallDataInterface;
use MagentoEavSetupEavSetupFactory;
class InstallData implements InstallDataInterface
{
protected $_eavSetupFactory;
public function __construct(
EavSetupFactory $eavSetupFactory
) {
$this->_eavSetupFactory = $eavSetupFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$eavSetup = $this->_eavSetupFactory->create(["setup"=>$setup]);
$eavSetup->addAttribute(
MagentoCatalogModelProduct::ENTITY,
'custom_product_attachment',
[
'group' => 'Product Attachment',
'type' => 'varchar',
'label' => 'Attachment',
'input' => 'file',
'backend' => 'MeetanshiProductAttachmentModelProductAttributeBackendFile',
'frontend' => '',
'class' => '',
'source' => '',
'global' => MagentoEavModelEntityAttributeScopedAttributeInterface::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' => true
]
);
}
}
MeetanshiProductAttachmentetcadminhtmldi.xml
<?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="MagentoCatalogUiDataProviderProductFormModifierPool" type="MagentoUiDataProviderModifierPool">
<arguments>
<argument name="modifiers" xsi:type="array">
<item name="custom_product_attachment" xsi:type="array">
<item name="class" xsi:type="string">MeetanshiProductAttachmentUiDataProviderProductFormModifierFile</item>
<item name="sortOrder" xsi:type="number">1000</item>
</item>
</argument>
</arguments>
</virtualType>
</config>
MeetanshiProductAttachmentModelProductAttributeBackendFile.php
<?php
namespace MeetanshiProductAttachmentModelProductAttributeBackend;
use MagentoFrameworkAppFilesystemDirectoryList;
use MagentoEavModelEntityAttributeBackendAbstractBackend;
class File extends AbstractBackend
{
protected $_file;
protected $_logger;
protected $_filesystem;
protected $_fileUploaderFactory;
public function __construct(
PsrLogLoggerInterface $logger,
MagentoFrameworkFilesystem $filesystem,
MagentoFrameworkFilesystemDriverFile $file,
MagentoMediaStorageModelFileUploaderFactory $fileUploaderFactory
) {
$this->_file = $file;
$this->_filesystem = $filesystem;
$this->_fileUploaderFactory = $fileUploaderFactory;
$this->_logger = $logger;
}
public function afterSave($object)
{
$path = $this->_filesystem->getDirectoryRead(
DirectoryList::MEDIA
)->getAbsolutePath(
'custom/product/attachment/'
);
$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['product']['tmp_name'][$this->getAttribute()->getName()])) {
return $this;
}
try {
$uploader = $this->_fileUpzloaderFactory->create(['fileId' => 'product['.$this->getAttribute()->getName().']']);
$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() != MagentoMediaStorageModelFileUploader::TMP_NAME_EMPTY) {
$this->_logger->critical($e);
}
}
return $this;
}
}
MeetanshiProductAttachmentUiDataProviderProductFormModifierFile.php
<?php
namespace MeetanshiProductAttachmentUiDataProviderProductFormModifier;
use MagentoFrameworkStdlibArrayManager;
use MagentoStoreModelStoreManagerInterface;
use MagentoCatalogUiDataProviderProductFormModifierAbstractModifier;
class File extends AbstractModifier
{
protected $arrayManager;
protected $storeManager;
public function __construct(
ArrayManager $arrayManager,
StoreManagerInterface $storeManager
) {
$this->arrayManager = $arrayManager;
$this->storeManager = $storeManager;
}
public function modifyMeta(array $meta)
{
$fieldCode = 'custom_product_attachment';
$elementPath = $this->arrayManager->findPath($fieldCode, $meta, null, 'children');
$containerPath = $this->arrayManager->findPath(static::CONTAINER_PREFIX . $fieldCode, $meta, null, 'children');
if (!$elementPath) {
return $meta;
}
$mediaUrl = $this->storeManager->getStore()
->getBaseUrl(MagentoFrameworkUrlInterface::URL_TYPE_MEDIA);
$meta = $this->arrayManager->merge(
$containerPath,
$meta,
[
'children' => [
$fieldCode => [
'arguments' => [
'data' => [
'config' => [
'elementTmpl' => 'Meetanshi_ProductAttachment/elements/file',
'media_url' => $mediaUrl
],
],
],
]
]
]
);
return $meta;
}
public function modifyData(array $data)
{
return $data;
}
}
MeetanshiProductAttachmentviewadminhtmlwebtemplateelementsfile.html
<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: media_url+'custom/product/attachment/'+$parent.source.data.product[code]" text="$parent.source.data.product[code]" target="_blank"></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 -->