diff --git a/.gitignore b/.gitignore
index 406a5a58d34aa64affc3725597a068b87ade26a1..61d970a274b8dc1a573bf8fd31083ab984197bff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,8 @@ atlassian*
 !/pub/media/customer/.htaccess
 /pub/media/downloadable/*
 !/pub/media/downloadable/.htaccess
+/pub/media/import/*
+!/pub/media/import/.htaccess
 /pub/media/theme/*
 /pub/media/theme_customization/*
 !/pub/media/theme_customization/.htaccess
diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
index d88a338509b794185dcf3da8d99ff151ed042d49..fb8019972debd0198bbe730e54562379ef0aedb2 100755
--- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php
@@ -1221,6 +1221,32 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
         return $this;
     }
 
+    /**
+     * Retrieving images from all columns and rows
+     *
+     * @param $bunch
+     * @return array
+     */
+    protected function _getAllBunchImages($bunch)
+    {
+        $allImagesFromBunch = [];
+        foreach ($bunch as $rowData) {
+            $rowData = $this->_customFieldsMapping($rowData);
+            foreach ($this->_imagesArrayKeys as $image) {
+                $dispersionPath =
+                    \Magento\Framework\File\Uploader::getDispretionPath($rowData[$image]);
+                $importImages = explode($this->getMultipleValueSeparator(), $rowData[$image]);
+                foreach ($importImages as $importImage) {
+                    $imageSting = mb_strtolower(
+                        $dispersionPath . '/' . preg_replace('/[^a-z0-9\._-]+/i', '', $importImage)
+                    );
+                    $allImagesFromBunch[$importImage] = $imageSting;
+                }
+            }
+        }
+        return $allImagesFromBunch;
+    }
+
     /**
      * Prepare all media files
      *
@@ -1243,7 +1269,17 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
                 ['entity_id', 'value']
             )->where('value IN (?)', $allImagesFromBunch)
         );
-        return $allMedia;
+        $result = array();
+        foreach ($allMedia as $image) {
+            $result[$image['value']] = [];
+            foreach ($this->_oldSku as $sku => $oldSkuData) {
+                if ($oldSkuData['entity_id'] != $image['entity_id']) {
+                    continue;
+                }
+                $result[$image['value']][] = $sku;
+            }
+        }
+        return $result;
     }
 
     /**
@@ -1274,6 +1310,8 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
             $uploadedGalleryFiles = [];
             $previousType = null;
             $prevAttributeSet = null;
+            $allImagesFromBunch = $this->_getAllBunchImages($bunch);
+            $existingImages = $this->_prepareAllMediaFiles($allImagesFromBunch);
 
             foreach ($bunch as $rowNum => $rowData) {
                 if (!$this->validateRow($rowData, $rowNum)) {
@@ -1364,6 +1402,95 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
                     ];
                 }
 
+                if (!$this->validateRow($rowData, $rowNum)) {
+                    continue;
+                }
+
+                // 5. Media gallery phase
+                $mediaGalleryImages = array();
+                $mediaGalleryLabels = array();
+                if (!empty($rowData[self::COL_MEDIA_IMAGE])) {
+                    $mediaGalleryImages =
+                        explode($this->getMultipleValueSeparator(), $rowData[self::COL_MEDIA_IMAGE]);
+                    if (isset($rowData['_media_image_label'])) {
+                        $mediaGalleryLabels =
+                            explode($this->getMultipleValueSeparator(), $rowData['_media_image_label']);
+                    } else {
+                        $mediaGalleryLabels = [];
+                    }
+                    if (count($mediaGalleryLabels) > count($mediaGalleryImages)) {
+                        $mediaGalleryLabels = array_slice($mediaGalleryLabels, 0, count($mediaGalleryImages));
+                    } elseif (count($mediaGalleryLabels) < count($mediaGalleryImages)) {
+                        $mediaGalleryLabels = array_pad($mediaGalleryLabels, count($mediaGalleryImages), '');
+                    }
+                }
+
+                foreach ($this->_imagesArrayKeys as $imageCol) {
+                    if (!empty($rowData[$imageCol])
+                        && ($imageCol != self::COL_MEDIA_IMAGE)
+                        && !in_array($rowData[$imageCol], $mediaGalleryImages)
+                    ) {
+                        $mediaGalleryImages[] = $rowData[$imageCol];
+                        if (isset($mediaGalleryLabels)) {
+                            $mediaGalleryLabels[] = isset($rowData[$imageCol . '_label'])
+                                ? $rowData[$imageCol . '_label']
+                                : '';
+                        } else {
+                            $mediaGalleryLabels[] = '';
+                        }
+                    }
+                }
+                $rowData[self::COL_MEDIA_IMAGE] = array();
+                foreach ($mediaGalleryImages as $mediaImage) {
+                    $imagePath = $allImagesFromBunch[$mediaImage];
+                    if (isset($existingImages[$imagePath]) && in_array($rowSku, $existingImages[$imagePath])) {
+                        if (!array_key_exists($mediaImage, $uploadedGalleryFiles)) {
+                            $uploadedGalleryFiles[$mediaImage] = $this->_uploadMediaFiles(
+                                trim($mediaImage),
+                                true
+                            );
+                        }
+                    } elseif (!isset($existingImages[$imagePath])) {
+                        if (!array_key_exists($mediaImage, $uploadedGalleryFiles)) {
+                            $uploadedGalleryFiles[$mediaImage] = $this->_uploadMediaFiles(
+                                trim($mediaImage),
+                                true
+                            );
+                            $newImagePath = $uploadedGalleryFiles[$mediaImage];
+                            $existingImages[$newImagePath][] = $rowSku;
+                        }
+                        $rowData[self::COL_MEDIA_IMAGE][] = $uploadedGalleryFiles[$mediaImage];
+                        if (!empty($rowData[self::COL_MEDIA_IMAGE]) && is_array($rowData[self::COL_MEDIA_IMAGE])) {
+                            $position = array_search($mediaImage, $mediaGalleryImages);
+                            foreach ($rowData[self::COL_MEDIA_IMAGE] as $mediaImage) {
+                                $mediaGallery[$rowSku][] = [
+                                    'attribute_id' => $this->getMediaGalleryAttributeId(),
+                                    'label' => isset($mediaGalleryLabels[$position]) ? $mediaGalleryLabels[$position] : '',
+                                    'position' => $position,
+                                    'disabled' => '',
+                                    'value' => $mediaImage,
+                                ];
+                            }
+                        }
+                    } else {
+                        foreach ($this->_imagesArrayKeys as $imageCol) {
+                            if (!empty($rowData[$imageCol]) && ($rowData[$imageCol] == $imagePath)) {
+                                $rowData[$imageCol] = '';
+                            }
+                        }
+                    }
+                    if (!isset($existingImages[$imagePath]) || in_array($rowSku, $existingImages[$imagePath])) {
+                        foreach ($this->_imagesArrayKeys as $imageCol) {
+                            if (!empty($rowData[$imageCol])
+                                && ($imageCol != self::COL_MEDIA_IMAGE)
+                                && isset($uploadedGalleryFiles[$rowData[$imageCol]])
+                            ) {
+                                $rowData[$imageCol] = $uploadedGalleryFiles[$rowData[$imageCol]];
+                            }
+                        }
+                    }
+                }
+
                 // 6. Attributes phase
                 $rowStore = (self::SCOPE_STORE == $rowScope)
                     ? $this->storeResolver->getStoreCodeToId($rowData[self::COL_STORE])
@@ -1470,7 +1597,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
             )->_saveProductGroupPrices(
                 $groupPrices
             )->_saveMediaGallery(
-                $bunch
+                $mediaGallery
             )->_saveProductAttributes(
                 $attributes
             );
@@ -1650,146 +1777,16 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
         }
     }
 
-    /**
-     * Upload images
-     *
-     * @param $bunch
-     * @return mixed
-     */
-    protected function getMediaGalleryData($bunch)
-    {
-        $allImagesFromBunch = [];
-        foreach ($bunch as $rowData) {
-            $rowData = $this->_customFieldsMapping($rowData);
-            foreach ($this->_imagesArrayKeys as $image) {
-                $dispersionPath =
-                    \Magento\Framework\File\Uploader::getDispretionPath($rowData[$image]);
-                $importImages = explode($this->getMultipleValueSeparator(), $rowData[$image]);
-                foreach ($importImages as $importImage) {
-                    $imageSting = mb_strtolower(
-                        $dispersionPath . '/' . preg_replace('/[^a-z0-9\._-]+/i', '', $importImage)
-                    );
-                    $allImagesFromBunch[$importImage] = $imageSting;
-                }
-            }
-        }
-        $existedImages = $this->_prepareAllMediaFiles($allImagesFromBunch);
-        $mediaGallery = [];
-        foreach ($bunch as $rowNum => $rowData) {
-            $uploadedGalleryFiles = [];
-            if (!$this->validateRow($rowData, $rowNum)) {
-                continue;
-            }
-            $rowSku = $rowData[self::COL_SKU];
-            $mediaGalleryImages = array();
-            $mediaGalleryLabels = array();
-            if (!empty($rowData[self::COL_MEDIA_IMAGE])) {
-                $mediaGalleryImages =
-                    explode($this->getMultipleValueSeparator(), $rowData[self::COL_MEDIA_IMAGE]);
-                if (isset($rowData['_media_image_label'])) {
-                    $mediaGalleryLabels =
-                        explode($this->getMultipleValueSeparator(), $rowData['_media_image_label']);
-                } else {
-                    $mediaGalleryLabels = [];
-                }
-                if (count($mediaGalleryLabels) > count($mediaGalleryImages)) {
-                    $mediaGalleryLabels = array_slice($mediaGalleryLabels, 0, count($mediaGalleryImages));
-                } elseif (count($mediaGalleryLabels) < count($mediaGalleryImages)) {
-                    $mediaGalleryLabels = array_pad($mediaGalleryLabels, count($mediaGalleryImages), '');
-                }
-            }
-
-            foreach ($this->_imagesArrayKeys as $imageCol) {
-                if (!empty($rowData[$imageCol])
-                    && ($imageCol != self::COL_MEDIA_IMAGE)
-                    && !in_array($rowData[$imageCol], $mediaGalleryImages)) {
-                    $mediaGalleryImages[] = $rowData[$imageCol];
-                    if (isset($mediaGalleryLabels)) {
-                        $mediaGalleryLabels[] = isset($rowData[$imageCol . '_label'])
-                            ? $rowData[$imageCol . '_label']
-                            : '';
-                    } else {
-                        $mediaGalleryLabels[] = '';
-                    }
-                }
-            }
-            $newSku = $this->getNewSku();
-            $entityIdNewProduct =
-                isset($newSku[$rowData[self::COL_SKU]]['entity_id'])
-                    ? $newSku[$rowData[self::COL_SKU]]['entity_id']
-                    : '';
-            $rowData[self::COL_MEDIA_IMAGE] = array();
-            foreach ($mediaGalleryImages as $mediaImage) {
-                if (!array_key_exists($mediaImage, $uploadedGalleryFiles)) {
-                    $imageIsSet = 0;
-                    $idIsSet = 0;
-                    foreach ($existedImages as $currentImage) {
-                        if ($currentImage['value'] == $allImagesFromBunch[$mediaImage]) {
-                            $imageIsSet = 1;
-                            if ($currentImage['entity_id'] == $entityIdNewProduct) {
-                                $idIsSet = 1;
-                            }
-                            break;
-                        }
-                    }
-                    if ($imageIsSet && $idIsSet) {
-                        if (!array_key_exists($mediaImage, $uploadedGalleryFiles)) {
-                            $uploadedGalleryFiles[$mediaImage] = $this->_uploadMediaFiles(
-                                trim($mediaImage),
-                                true
-                            );
-                        }
-                        $rowData[self::COL_MEDIA_IMAGE][] = $uploadedGalleryFiles[$mediaImage];
-                    } elseif (!$imageIsSet && !$idIsSet) {
-                        $newAddedImages = [];
-                        if (!array_key_exists($mediaImage, $uploadedGalleryFiles)) {
-                            $uploadedGalleryFiles[$mediaImage] = $this->_uploadMediaFiles(
-                                trim($mediaImage),
-                                true
-                            );
-                            $newAddedImages['entity_id'] = $entityIdNewProduct;
-                            $newAddedImages['value'] = $uploadedGalleryFiles[$mediaImage];
-                            $existedImages[] = $newAddedImages;
-                        }
-                        $rowData[self::COL_MEDIA_IMAGE][] = $uploadedGalleryFiles[$mediaImage];
-
-                        foreach ($this->_imagesArrayKeys as $imageCol) {
-                            if (!empty($rowData[$imageCol]) && ($imageCol != self::COL_MEDIA_IMAGE)) {
-                                if(isset($uploadedGalleryFiles[$rowData[$imageCol]])) {
-                                    $rowData[$imageCol] = $uploadedGalleryFiles[$rowData[$imageCol]];
-                                }
-                            }
-                        }
-                        if (!empty($rowData[self::COL_MEDIA_IMAGE]) && is_array($rowData[self::COL_MEDIA_IMAGE])) {
-                            $position = array_search($mediaImage, $mediaGalleryImages);
-                            foreach ($rowData[self::COL_MEDIA_IMAGE] as $mediaImage) {
-                                $mediaGallery[$rowSku][] = [
-                                    'attribute_id' => $this->getMediaGalleryAttributeId(),
-                                    'label' => isset($mediaGalleryLabels[$position]) ? $mediaGalleryLabels[$position] : '',
-                                    'position' => $position,
-                                    'disabled' => '',
-                                    'value' => $mediaImage,
-                                ];
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return $mediaGallery;
-    }
-
     /**
      * Save product media gallery.
      *
-     * @param array $bunch
+     * @param array $mediaGalleryData
      * @return $this
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * @SuppressWarnings(PHPMD.NPathComplexity)
      */
-    protected function _saveMediaGallery($bunch)
+    protected function _saveMediaGallery(array $mediaGalleryData)
     {
-        $mediaGalleryData = $this->getMediaGalleryData($bunch);
         if (empty($mediaGalleryData)) {
             return $this;
         }