2

I have created a script file to delete all the duplicate product images.

Here is the code I used.

<?php
 error_reporting(E_ALL);
 use \Magento\Framework\App\Bootstrap;
 require __DIR__ . '/app/bootstrap.php';
 $bootstrap = Bootstrap::create(BP, $_SERVER);
 $obj = $bootstrap->getObjectManager(); 
 $app_state = $obj->get('\Magento\Framework\App\State');
 $app_state->setAreaCode('global');
 ini_set('memory_limit','10240M');
 ini_set('max_execution_time', 0); 
 set_time_limit(0); 


 $mediaApi = $obj->create('\Magento\Catalog\Model\Product\Gallery\Processor');
 $storeManager = $obj->get('\Magento\Store\Model\StoreManagerInterface');
 $mediaUrl = $storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
 $directoryList=$obj->get('\Magento\Framework\App\Filesystem\DirectoryList');
 $path = $directoryList->getPath('media'); 
$productCollection=$obj->create('Magento\Catalog\Model\ResourceModel\Product\Collection');
$_products = $productCollection->addAttributeToSelect('*')->load();
$i =0;
$total = count($_products);
$count = 0;
foreach($_products as $_prod)
{
    $_product = $obj->create('Magento\Catalog\Model\Product')->load($_prod->getId());
$_md5_values = array();

$base_image = $_product->getImage();

if($base_image != 'no_selection')
{
    $mediaUrl = $storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
    $filepath = $path.'/catalog/product' . $base_image ;
    if(file_exists($filepath))
        $_md5_values[] = md5(file_get_contents($filepath));
}
$i ++;
 // echo "\r\n processing product $i of $total ";

 // Loop through product images
 $_images = $_product->getMediaGalleryImages();

 if($_images)
   {
    foreach($_images as $_image)
    {
        //protected base image
        if($_image->getFile() == $base_image)
            continue;
        $filepath = $path.'/catalog/product' .$_image->getFile();
        if(file_exists($filepath))
            $md5 = md5(file_get_contents($filepath));
        else
            continue;

        if( in_array( $md5, $_md5_values ))
        {
            $mediaApi->removeImage($_product, $_image->getFile());

            echo "\r\n removed duplicate image from ".$_product->getSku();
            $count++;
        }
        else 
        {
            $_md5_values[] = $md5;
        }
    }
  }
  $_product->save();
}

Above script removes if same image file exist for a product, then only it will remove it,

In my case if same image imported multiple times for a product, that is created as image.jpg and image_1.jpg.

I need to remove all duplicate images(which are _1,_2 etc) for all the products.

Please correct me in the above script, to remove duplicate image for the product. Thanks

1
  • This works, and it still works currently on Magento 2.4.5-p1. But this runs a save method on Product in every loop, so this will go horribly slow when running on a big collection. For example our shop has +200k products, so if there are a few thousand with duplicate images the script would take hours.
    – Jacques
    Jun 15 at 8:01

3 Answers 3

1

Make sure you are working on the admin store view:

        $this->storeManager->setCurrentStore(0);
        $product->setStoreId(0);

Use the Media Gallery 'Entries' instead:

    $gallery = $product->getMediaGalleryEntries();

Iterate with:

    foreach ($gallery as $key => $galleryImage) {

You can access the files with:

        $galleryImage->getFile()

Then when you have a duplicate:

                unset($gallery[$key]);

Then set the gallery to your revised one:

        $product->setMediaGalleryEntries($gallery);

Then save the product using the product repository:

        $this->productRepository->save($product);
3
  • 1
    where is the condition here to test the product has duplicate image? Feb 4, 2020 at 9:52
  • In your question you are using md5 to compare your files. You could just check file sizes or filenames but you took the md5 approach, which I think is a good one. Did you just copy and paste your question code without understanding what it does? Feb 4, 2020 at 11:31
  • Please Provide Full Code.,in this i cant understand. Jul 4, 2020 at 9:27
0

You can Buy Extension available on MP that can clean your unused Catalog Images as well as Duplicate entries You can Clean theme manually or using CRON

0

If anyone needs a full script to remove duplicate product images, here it is. This will not remove the image with any image type (small image, thumbnail image, etc.) tagged with the image.

<?php
error_reporting(E_ALL);
use \Magento\Framework\App\Bootstrap;
require __DIR__ . '/app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$obj = $bootstrap->getObjectManager(); 
$app_state = $obj->get('\Magento\Framework\App\State');
$app_state->setAreaCode('global');
ini_set('memory_limit','10240M');
ini_set('max_execution_time', 0); 
set_time_limit(0);

$mediaApi = $obj->create('\Magento\Catalog\Model\Product\Gallery\Processor');
$storeManager = $obj->get('\Magento\Store\Model\StoreManagerInterface');
$storeManager->setCurrentStore(0);
$mediaUrl = $storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$directoryList=$obj->get('\Magento\Framework\App\Filesystem\DirectoryList');
$path = $directoryList->getPath('media'); 
$productCollection=$obj->create('Magento\Catalog\Model\ResourceModel\Product\Collection');
$_products = $productCollection->addAttributeToSelect('*')->load();

$productRepository = $obj->get('\Magento\Catalog\Model\ProductRepository');
$i =0;
$total = count($_products);
$count = 0;
$productCount = array();
foreach($_products as $_prod) {
    $_product = $productRepository->getById($_prod->getId());
    $_product->setStoreId(0);
    $_md5_values = array();
    $base_image = $_product->getImage();
    
    if($base_image != 'no_selection') {
        $mediaUrl = $storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
        $filepath = $path.'/catalog/product' . $base_image ;
        if (file_exists($filepath)) {
            $_md5_values[] = md5(file_get_contents($filepath));            
        }
        $i++;

        echo "\r\n processing product $i of $total ";
        // Loop through product images
        $gallery = $_product->getMediaGalleryEntries();
        if ($gallery) {
            foreach ($gallery as $key => $galleryImage) {
                //protected base image
                if($galleryImage->getFile() == $base_image) {
                    continue;
                }
                $filepath = $path.'/catalog/product' .$galleryImage->getFile();

                if(file_exists($filepath)) {
                    $md5 = md5(file_get_contents($filepath));
                } else {
                    continue;
                }

                if( in_array( $md5, $_md5_values )) {
                    if (count($galleryImage->getTypes()) > 0) {
                        continue;
                    }
                    unset($gallery[$key]);
                    echo "\r\n removed duplicate image from ".$_product->getSku();
                    $count++;
                } else {
                    $_md5_values[] = $md5;
                }
            }
            
            $_product->setMediaGalleryEntries($gallery);
            $productRepository->save($_product);            
        }
        //$_product->save();
    }
}
die("Script Completed");
1
  • How do I use this?
    – Jesse
    Mar 12 at 2:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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