I am trying to upload Thumbnail image and image for category page but it is neither uploading nor showing any error.
I have cleared cache and also done indexing but still no output
Any solution??
categoryimage-upload
I am trying to upload Thumbnail image and image for category page but it is neither uploading nor showing any error.
I have cleared cache and also done indexing but still no output
Any solution??
If you are using PHP 7 then go to
lib/Varien/File/Uploader.php
Find the following code
$params['object']->$params['method']($this->_file['tmp_name']);
And replace it with
$params['object']->{$params['method']}($this->_file['tmp_name']);
This is quite a big answer.
In Magento 2.1.0 you need to apply a patch to create a additional file upload attribute for category.
As they are using hardcoded values for image attribute on many places. for more details have a look at link1 and link2
Steps to apply a patch.
1) Edit composer.json file located at root directory as follows.
{
"name": "magento/project-community-edition",
"description": "eCommerce Platform for Growth (Community Edition)",
"type": "project",
"version": "2.1.0",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"repositories": [
{
"type": "composer",
"url": "https://repo.magento.com/"
}
],
"require": {
"magento/product-community-edition": "2.1.0",
"cweagans/composer-patches": "~1.4.0",
"composer/composer": "@alpha"
},
"require-dev": {
"phpunit/phpunit": "4.1.0",
"squizlabs/php_codesniffer": "1.5.3",
"phpmd/phpmd": "2.3.*",
"pdepend/pdepend": "2.2.2",
"sjparkinson/static-review": "~4.1",
"fabpot/php-cs-fixer": "~1.2",
"lusitanian/oauth": "~0.3 <=0.7.0"
},
"config": {
"use-include-path": true
},
"autoload": {
"psr-4": {
"Magento\\Framework\\": "lib/internal/Magento/Framework/",
"Magento\\Setup\\": "setup/src/Magento/Setup/",
"Magento\\": "app/code/Magento/"
},
"psr-0": {
"": "app/code/"
},
"files": [
"app/etc/NonComposerComponentRegistration.php"
]
},
"autoload-dev": {
"psr-4": {
"Magento\\Sniffs\\": "dev/tests/static/framework/Magento/Sniffs/",
"Magento\\Tools\\": "dev/tools/Magento/Tools/",
"Magento\\Tools\\Sanity\\": "dev/build/publication/sanity/Magento/Tools/Sanity/",
"Magento\\TestFramework\\Inspection\\": "dev/tests/static/framework/Magento/TestFramework/Inspection/",
"Magento\\TestFramework\\Utility\\": "dev/tests/static/framework/Magento/TestFramework/Utility/"
}
},
"minimum-stability": "alpha",
"prefer-stable": true,
"extra": {
"patches": {
"magento/module-catalog": {
"Fix: https://github.com/magento/magento2/issues/5438": "patches/Patch-Magento_Catalog-M2.1.0-image-attribute-backend-model-hardcoded-attribute-code-removal.patch"
},
"magento/module-ui": {
"Fix: https://github.com/magento/magento2/issues/5438": "patches/Patch-Magento_Ui-M2.1.0-allow-backend-to-know-the-origin-input-of-the-upload-request.patch"
}
},
"magento-force": "override"
}
}
As mentioned on link2 above newly added code is in extra and require.
2) Create a patches folder on root directory.
3) Create file Patch-Magento_Catalog-M2.1.0-image-attribute-backend-model-hardcoded-attribute-code-removal.patch under patches folder with following contains.
--- Controller/Adminhtml/Category/Save.php.org 2016-08-03 21:35:33.772109252 +0200
+++ Controller/Adminhtml/Category/Save.php 2016-08-03 21:36:33.982229407 +0200
@@ -6,6 +6,7 @@
namespace Magento\Catalog\Controller\Adminhtml\Category;
use Magento\Store\Model\StoreManagerInterface;
+use \Magento\Catalog\Api\Data\CategoryAttributeInterface;
/**
* Class Save
@@ -49,6 +50,11 @@
private $storeManager;
/**
+ * @var \Magento\Eav\Model\Config
+ */
+ private $eavConfig;
+
+ /**
* Constructor
*
* @param \Magento\Backend\App\Action\Context $context
@@ -62,37 +68,15 @@
\Magento\Framework\Controller\Result\RawFactory $resultRawFactory,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Magento\Framework\View\LayoutFactory $layoutFactory,
- StoreManagerInterface $storeManager
+ StoreManagerInterface $storeManager,
+ \Magento\Eav\Model\Config $eavConfig
) {
parent::__construct($context);
$this->resultRawFactory = $resultRawFactory;
$this->resultJsonFactory = $resultJsonFactory;
$this->layoutFactory = $layoutFactory;
$this->storeManager = $storeManager;
- }
-
- /**
- * Filter category data
- *
- * @param array $rawData
- * @return array
- */
- protected function _filterCategoryPostData(array $rawData)
- {
- $data = $rawData;
- // @todo It is a workaround to prevent saving this data in category model and it has to be refactored in future
- if (isset($data['image']) && is_array($data['image'])) {
- if (!empty($data['image']['delete'])) {
- $data['image'] = null;
- } else {
- if (isset($data['image'][0]['name']) && isset($data['image'][0]['tmp_name'])) {
- $data['image'] = $data['image'][0]['name'];
- } else {
- unset($data['image']);
- }
- }
- }
- return $data;
+ $this->eavConfig = $eavConfig;
}
/**
@@ -126,7 +110,7 @@
$this->storeManager->setCurrentStore($store->getCode());
$parentId = isset($categoryPostData['parent']) ? $categoryPostData['parent'] : null;
if ($categoryPostData) {
- $category->addData($this->_filterCategoryPostData($categoryPostData));
+ $category->addData($categoryPostData);
if ($isNewCategory) {
$parentCategory = $this->getParentCategory($parentId, $storeId);
$category->setPath($parentCategory->getPath());
@@ -247,22 +231,29 @@
);
}
- /**
- * Image data preprocessing
- *
- * @param array $data
- *
- * @return array
- */
public function imagePreprocessing($data)
{
- if (empty($data['image'])) {
- unset($data['image']);
- $data['image']['delete'] = true;
+ $entityType = $this->eavConfig->getEntityType(CategoryAttributeInterface::ENTITY_TYPE_CODE);
+
+ foreach ($entityType->getAttributeCollection() as $attributeModel) {
+ $attributeCode = $attributeModel->getAttributeCode();
+ $backendModel = $attributeModel->getBackend();
+
+ if (isset($data[$attributeCode])) {
+ continue;
+ }
+
+ if (!$backendModel instanceof \Magento\Catalog\Model\Category\Attribute\Backend\Image) {
+ continue;
+ }
+
+ $data[$attributeCode] = false;
}
+
return $data;
}
+
/**
* Converting inputs from string to boolean
*
--- Controller/Adminhtml/Category/Image/Upload.php.org 2016-08-01 20:36:22.014237780 +0200
+++ Controller/Adminhtml/Category/Image/Upload.php 2016-08-01 20:36:25.292475257 +0200
@@ -50,8 +50,10 @@
*/
public function execute()
{
+ $imageId = $this->_request->getParam('param_name', 'image');
+
try {
- $result = $this->imageUploader->saveFileToTmpDir('image');
+ $result = $this->imageUploader->saveFileToTmpDir($imageId);
$result['cookie'] = [
'name' => $this->_getSession()->getName(),
--- Model/Category/Attribute/Backend/Image.php.org 2016-08-03 21:36:05.695112561 +0200
+++ Model/Category/Attribute/Backend/Image.php 2016-08-03 21:36:46.829828298 +0200
@@ -13,6 +13,8 @@
class Image extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
{
+ const ADDITIONAL_DATA_SUFFIX = '_additional_data';
+
/**
* @var \Magento\MediaStorage\Model\File\UploaderFactory
*
@@ -21,8 +23,6 @@
protected $_uploaderFactory;
/**
- * Filesystem facade
- *
* @var \Magento\Framework\Filesystem
*
* @deprecated
@@ -30,8 +30,6 @@
protected $_filesystem;
/**
- * File Uploader factory
- *
* @var \Magento\MediaStorage\Model\File\UploaderFactory
*
* @deprecated
@@ -46,15 +44,11 @@
protected $_logger;
/**
- * Image uploader
- *
* @var \Magento\Catalog\Model\ImageUploader
*/
private $imageUploader;
/**
- * Image constructor.
- *
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Filesystem $filesystem
* @param \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory
@@ -70,8 +64,50 @@
}
/**
- * Get image uploader
+ * @param $value
+ * @return string|bool
+ */
+ protected function getUploadedImageName($value)
+ {
+ if (!is_array($value)) {
+ return false;
+ }
+
+ if (!count($value)) {
+ return false;
+ }
+
+ $imageData = reset($value);
+
+ if (!isset($imageData['name'])) {
+ return false;
+ }
+
+ return $imageData['name'];
+ }
+
+ /**
+ * Avoiding saving potential upload data to DB
*
+ * @param \Magento\Framework\DataObject $object
+ * @return $this
+ */
+ public function beforeSave($object)
+ {
+ $attributeName = $this->getAttribute()->getName();
+ $value = $object->getData($attributeName);
+
+ if ($value === false || (is_array($value) && isset($value['delete']) && $value['delete'] === true)) {
+ $object->setData($attributeName, '');
+ } else if ($imageName = $this->getUploadedImageName($value)) {
+ $object->setData($attributeName . self::ADDITIONAL_DATA_SUFFIX, $value);
+ $object->setData($attributeName, $imageName);
+ }
+
+ return parent::beforeSave($object);
+ }
+
+ /**
* @return \Magento\Catalog\Model\ImageUploader
*
* @deprecated
@@ -80,9 +116,10 @@
{
if ($this->imageUploader === null) {
$this->imageUploader = \Magento\Framework\App\ObjectManager::getInstance()->get(
- 'Magento\Catalog\CategoryImageUpload'
+ \Magento\Catalog\CategoryImageUpload::class
);
}
+
return $this->imageUploader;
}
@@ -94,15 +131,18 @@
*/
public function afterSave($object)
{
- $image = $object->getData($this->getAttribute()->getName(), null);
+ $value = $object->getData($this->getAttribute()->getName() . self::ADDITIONAL_DATA_SUFFIX);
- if ($image !== null) {
- try {
- $this->getImageUploader()->moveFileFromTmp($image);
- } catch (\Exception $e) {
- $this->_logger->critical($e);
- }
+ if (!$imageName = $this->getUploadedImageName($value)) {
+ return $this;
}
+
+ try {
+ $this->getImageUploader()->moveFileFromTmp($imageName);
+ } catch (\Exception $e) {
+ $this->_logger->critical($e);
+ }
+
return $this;
}
}
--- Model/Category/DataProvider.php.org 2016-08-01 21:35:43.567609510 +0200
+++ Model/Category/DataProvider.php 2016-08-01 21:43:07.800993338 +0200
@@ -203,14 +203,24 @@
$category = $this->getCurrentCategory();
if ($category) {
$categoryData = $category->getData();
+
$categoryData = $this->addUseDefaultSettings($category, $categoryData);
$categoryData = $this->addUseConfigSettings($categoryData);
$categoryData = $this->filterFields($categoryData);
- if (isset($categoryData['image'])) {
- unset($categoryData['image']);
- $categoryData['image'][0]['name'] = $category->getData('image');
- $categoryData['image'][0]['url'] = $category->getImageUrl();
+
+ foreach ($category->getAttributes() as $attributeCode => $attribute) {
+ $backendModel = $attribute->getBackend();
+
+ if ($backendModel instanceof \Magento\Catalog\Model\Category\Attribute\Backend\Image) {
+ if (isset($categoryData[$attributeCode])) {
+ unset($categoryData[$attributeCode]);
+
+ $categoryData[$attributeCode][0]['name'] = $category->getData($attributeCode);
+ $categoryData[$attributeCode][0]['url'] = $category->getImageUrl($attributeCode);
+ }
+ }
}
+
$this->loadedData[$category->getId()] = $categoryData;
}
return $this->loadedData;
--- Model/Category.php.org 2016-08-01 21:41:47.535876208 +0200
+++ Model/Category.php 2016-08-01 21:42:57.916422400 +0200
@@ -652,14 +652,15 @@
}
/**
- * Retrieve image URL
+ * @param $attributeCode
*
- * @return string
+ * @return bool|string
+ * @throws \Magento\Framework\Exception\LocalizedException
*/
- public function getImageUrl()
+ public function getImageUrl($attributeCode = 'image')
{
$url = false;
- $image = $this->getImage();
+ $image = $this->getData($attributeCode);
if ($image) {
if (is_string($image)) {
$url = $this->_storeManager->getStore()->getBaseUrl(
4) Create file Patch-Magento_Ui-M2.1.0-allow-backend-to-know-the-origin-input-of-the-upload-request.patch under patches folder with following contains.
--- view/base/web/js/form/element/file-uploader.js.org 2016-08-01 20:33:22.866555339 +0200
+++ view/base/web/js/form/element/file-uploader.js 2016-08-01 20:33:42.384061881 +0200
@@ -302,7 +302,13 @@
allowed = this.isFileAllowed(file);
if (allowed.passed) {
- $(e.target).fileupload('process', data).done(function () {
+ var $target = $(e.target);
+
+ $target.on('fileuploadsend', function(event, postData) {
+ postData.data.set('param_name', this.paramName);
+ }.bind(data));
+
+ $target.fileupload('process', data).done(function () {
data.submit();
});
} else {
5) Run following Commands
- composer validate composer.json (To Vallidate composer file).
- composer update
- php bin/magento setup:upgrade
6) Now its time to create your module for new file upload option.
Create a file
app\code\Vendor\Module\registration.php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
"Vendor_Module",
__DIR__
);
Create a file
app\code\Vendor\Module\etc\module.xml
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<module name="Vendor_Module" setup_version="1.0" />
</config>
Create a file
app\code\Vendor\Module\Setup\InstallData.php
<?php
namespace Vendor\Module\Setup;
use Magento\Framework\Module\Setup\Migration;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Catalog\Setup\CategorySetupFactory;
class InstallData implements InstallDataInterface
{
public function __construct(CategorySetupFactory $categorySetupFactory)
{
$this->categorySetupFactory = $categorySetupFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$installer = $setup;
$installer->startSetup();
$categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);
$entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Category::ENTITY);
$attributeSetId = $categorySetup->getDefaultAttributeSetId($entityTypeId);
$categorySetup->removeAttribute(
\Magento\Catalog\Model\Category::ENTITY, 'featured_image' );
$categorySetup->addAttribute(
\Magento\Catalog\Model\Category::ENTITY, 'featured_image', [
'type' => 'varchar',
'label' => 'Featured Image',
'input' => 'image',
'backend' => 'Magento\Catalog\Model\Category\Attribute\Backend\Image',
'required' => false,
'sort_order' => 5,
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'group' => 'General Information',
]
);
$installer->endSetup();
}
}
Create a file
app\code\Vendor\Module\view\adminhtml\ui_component\category_form.xml
<?xml version="1.0" encoding="UTF-8" ?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="content">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="label" xsi:type="string" translate="true">Content</item>
<item name="collapsible" xsi:type="boolean">true</item>
<item name="sortOrder" xsi:type="number">10</item>
</item>
</argument>
<field name="featured_image">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">string</item>
<item name="source" xsi:type="string">category</item>
<item name="label" xsi:type="string" translate="true">Featured Image</item>
<item name="visible" xsi:type="boolean">true</item>
<item name="formElement" xsi:type="string">fileUploader</item>
<item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
<item name="previewTmpl" xsi:type="string">Magento_Catalog/image-preview</item>
<item name="required" xsi:type="boolean">false</item>
<item name="sortOrder" xsi:type="number">40</item>
<item name="uploaderConfig" xsi:type="array">
<item name="url" xsi:type="url" path="catalog/category_image/upload"/>
</item>
</item>
</argument>
</field>
</fieldset>
</form>
Hope this helps you.
Best Answer
Verify the existence of
media/catalog/category
directory with correct permissionsCheck your
media/catalog/category
folder is named with.jpg
or.png
. If yes, then delete these folder.