7

I'm working with a Magento 2 project that need to upload image using a POST endpoint

How can I send image content to this endpoint?

Or I have to base64 the image at client side and send the base64 content to POST endpoint?

Thank you very much.

5 Answers 5

10

If you want to upload product image using rest API you need to pass below parameters in your request:

Your media upload url - http://127.0.0.1/megento2/index.php/rest/V1/products/{sku}/media.

Method name - Post

Below are the body parameters :

[
  {
    "id": 0,
    "media_type": "test",
    "label": "test",
    "position": 0,
    "disabled": true,
    "types": [
      "thumbnail"
    ],
    "file": "test.png",
    "content": {
      "base64_encoded_data": "Here i have passed base64_encoded data of image",
      "type": "file/png",
      "name": "test.png"
    },
    }
  }
]

Note : Make sure you pass base64_encoded_data of image.

4
  • Hi Manthan Dave, so basically Magento 2 API does not support file input, right? I worked with Laravel API, and they support file input, wonder why Magento 2 doesn't do this?
    – 0xh8h
    Commented Jun 23, 2017 at 9:56
  • 1
    Yes Bang on @piavgh - Magento 2 rest api for media upload its not supporting file input , you must need to pass base64 encoded image. or you can create your custom observer for that . Commented Jun 23, 2017 at 10:19
  • Thank you Manthan. Can you please tell me more about the custom observer approach? I didn't understand it clearly. I think that whether we use observer or not, we still have to get the file from api, right? But this is what Magento 2 API doesn't support.
    – 0xh8h
    Commented Jun 23, 2017 at 15:46
  • Well better to do one thing , send base64_encoded image and decode it where you needed file format. using base64_decode and then do put_file_contents with image name it will create new image for you Commented Jun 23, 2017 at 16:14
2

Pass files as below in API payload

{
    "files": [
        {
            "type": "image/jpeg",
            "name": "test.png",
            "base64_encoded_data": "your base64 encoded image content"
        }
    ]
}

Inside your Model class

<?php

namespace UrVendor\UrModule\Model;

use Magento\Framework\Api\ImageProcessorInterface;
use Magento\Framework\Api\Data\ImageContentInterfaceFactory;

class UrClassName implements UrClassNameInterface
{
    private $imageProcessor;
    private $imageContentFactory;

    public function __construct(
        .....
        ImageProcessorInterface $imageProcessor,
        ImageContentInterfaceFactory $imageContentFactory
    ) {
        .....
        $this->imageProcessor = $imageProcessor;
        $this->imageContentFactory = $imageContentFactory;
    }
    
    public function urApiFunction($files) {
        if (count($files) > 0) {
            $destinationFolder = 'test';
            foreach ($files as $file) {
                $imageContent = $this->imageContentFactory->create();
                $imageContent->setBase64EncodedData($file['base64_encoded_data']);
                $imageContent->setType($file['type']);
                $imageContent->setName($file['name']);
                $filename = $this->imageProcessor->processImageContent($destinationFolder, $imageContent);
            }
        }
    
    }
}
1

By default it is necessary to send the image encoded in base 64.

For a project, a client asked me to prevent the images from being sent encoded through the API to reduce the transmission time when the products of the catalog were updated. As it is obviously not possible to send the image files through the API the solution was a plugin that modifies the behavior of magento 2 to search the image files in the folder "pub/media/import"

https://github.com/olivertar/m2_api_product_images

1
  • This thing is just GOLD! Need to do a Pull Request tho, to change the ['data'] thing which was suggested in the issue by "cad-software" :) Commented Nov 24, 2020 at 13:13
0

I did what Manthan Dave has sent, but when I do it via Magento API,looks like it makes a copy and so I always get an extra image. IS there anything I have to do? (I dont have enough reputation to comment, sorry!)

0
-1

To upload image you can use jquery fileupload. Here is example

view/frontend/layout/default.xml (layout you need)

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <css media="all" src="jquery/fileUploader/css/jquery.fileupload-ui.css"/>
    </head>
</page>

You could create widget or just use require js

$wrapper.find('input[type=file]').fileupload({
    dataType: 'json',
    formData: {
       'form_key': window.FORM_KEY
    },
    limitMultiFileUploads: 1,
    acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
    done: function (e, data) {
    }
});

More information here https://github.com/blueimp/jQuery-File-Upload

and your Controller

<?php
namespace Vendor\Module\Controller;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\UrlInterface;

class Upload extends \Magento\Framework\App\Action\Action
{
    /**
     * @var \Magento\Framework\Controller\Result\JsonFactory
     */
    protected $resultJsonFactory;

    /**
     * @var \Magento\MediaStorage\Model\File\UploaderFactory
     */
    protected $uploaderFactory;

    /**
     * @var \Magento\Framework\Filesystem\Directory\Write
     */
    protected $mediaDirectoryWrite;

    /**
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
     * @param \Magento\Framework\Filesystem $filesystem
     * @param \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory
     */
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory
    ) {
        parent::__construct($context);

        $this->resultJsonFactory = $resultJsonFactory;
        $this->uploaderFactory = $uploaderFactory;
        $this->mediaDirectoryWrite = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
    }

    /**
     * @return \Magento\Framework\Controller\Result\JsonFactory
     */
    public function execute()
    {
        if (!$this->mediaDirectoryWrite->isWritable('MEDIA_PATH')) {
            $this->mediaDirectoryWrite->create('MEDIA_PATH');
        }

        $resultJson = $this->resultJsonFactory->create();
        try {
            $targetPath = $this->mediaDirectoryWrite->getAbsolutePath('MEDIA_PATH');
            $uploader = $this->uploaderFactory->create([
                'fileId' => 'file'
            ]);
            $uploader->setAllowedExtensions(['gif', 'png', 'jpg', 'jpeg']);
            $uploader->setAllowRenameFiles(true);
            $uploader->setFilesDispersion(true);
            $result = $uploader->save($targetPath);

            $result['file'] = ltrim($result['file'], '/');
            $result['url'] = $this->_url->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA])
                . 'MEDIA_PATH'
                . '/'
                . $result['file'];
        } catch (\Exception $e) {
            $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }

        return $resultJson->setData($result);
    }
}
6
  • Thank Nicholas. But I need to send image to REST API, not controller as you suggested.
    – 0xh8h
    Commented Jun 22, 2017 at 2:56
  • Look at devdocs.magento.com/swagger/index_20.html how POST was implemented in catalogProductRepositoryV1 method. In this way you should send base64encoded data. Commented Jun 22, 2017 at 3:10
  • You mean this part "content": { "base64EncodedData": "string", "type": "string", "name": "string" }, right?
    – 0xh8h
    Commented Jun 22, 2017 at 3:12
  • yes, in mediaGalleryEntries Commented Jun 22, 2017 at 3:13
  • I strongly disagree with your statement. Using a custom controller instead of the provided API is not recommendable. Why would any webserver disallow a JSON post but allow a file upload?
    – ooxi
    Commented Jun 25, 2017 at 19:25

Your Answer

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

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