How to import a product image from an URL in Magento 2?

Magento 2 is gaining popularity with each passing day. Many vendors decide to use this platform for their eCommerce business. Migrating data from other platforms and services has always been a popular task, but it has become even more essential today. In this article, I will demonstrate how to easily import product images from an external URL.

Magento 2 import handles saving product images pretty well, but the optimized images should already be located on your server. With the service described below, I will show you how to grab an image URL and turn it into a product image. All the necessary logic is wrapped into this service, so it can be called from your controllers, observers, via Magento 2 plugins or from any other kind of entry point that you want.

I assume you’ve already registered your extension as VendorName_ExtensionName and it is located in the app/code/VendorName/ExtensionName. The code of the service:

<?php
/**
 * file location:
 * app/code/VendorName/ExtensionName/Service/ImportImageService.php
 */

namespace VendorName\ExtensionName\Service;

use Magento\Catalog\Model\Product;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem\Io\File;

/**
 * Class ImportImageService
 * assign images to products by image URL
 */
class ImportImageService
{
    /**
     * Directory List
     *
     * @var DirectoryList
     */
    protected $directoryList;

    /**
     * File interface
     *
     * @var File
     */
    protected $file;

    /**
     * ImportImageService constructor
     *
     * @param DirectoryList $directoryList
     * @param File $file
     */
    public function __construct(
        DirectoryList $directoryList,
        File $file
    ) {
        $this->directoryList = $directoryList;
        $this->file = $file;
    }

    /**
     * Main service executor
     *
     * @param Product $product
     * @param string $imageUrl
     * @param array $imageType
     * @param bool $visible
     *
     * @return bool
     */
    public function execute($product, $imageUrl, $visible = false, $imageType = [])
    {
        /** @var string $tmpDir */
        $tmpDir = $this->getMediaDirTmpDir();
        /** create folder if it is not exists */
        $this->file->checkAndCreateFolder($tmpDir);
        /** @var string $newFileName */
        $newFileName = $tmpDir . baseName($imageUrl);
        /** read file from URL and copy it to the new destination */
        $result = $this->file->read($imageUrl, $newFileName);
        if ($result) {
            /** add saved file to the $product gallery */
            $product->addImageToMediaGallery($newFileName, $imageType, true, $visible);
        }

        return $result;
    }

    /**
     * Media directory name for the temporary file storage
     * pub/media/tmp
     *
     * @return string
     */
    protected function getMediaDirTmpDir()
    {

        return $this->directoryList->getPath(DirectoryList::MEDIA) . DIRECTORY_SEPARATOR . 'tmp';
    }
}

The service can be included in any necessary place and its execute method will be called with the following params:

  • $product – loaded product instance, the image will be added to it;
  • $imageUrl – external image URL;
  • $visible – an image will be hidden by default. You may make it visible, simply by passing boolean “true”;
  • $imageType – an array, optional param, where you can specify whether to set an image as a main image, a small image or a thumbnail (or any combination of those). E.g: [‘image’, ‘small_image’, ‘thumbnail’].

Pretty simple, huh? I hope this service will spare you some time when migrating data.

Thanks for reading!

Read more: