I want to upload images using graphql using file not base64, can anyone tell me how can I implement this?
Thanks in advance!!
First convert your image into base64 then use that base64 string in to graphql input.
<?php
namespace Vendor\Module\Model\Upload;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\Driver\File;
class UploadImage implements ResolverInterface
{
public function __construct(
Filesystem $fileSystem,
File $fileDriver
) {
$this->fileSystem = $fileSystem;
$this->fileDriver = $fileDriver;
}
public function resolve(
Field $field,
$context,
ResolveInfo $info,
array $value = null,
array $args = null
) {
$this->uploadFile($fileData);
}
public function uploadFile($fileData)
{
$uploadedFileName = "";
$fileName = '';
if (isset($fileData['name'])) {
$fileName = $fileData['name'];
} else {
$fileName = rand() . time();
}
if (isset($fileData['filecontent'])) {
$mediaPath = $this->fileSystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath();
$originalPath = 'ModuleName/Attachments/';
$mediaFullPath = $mediaPath . $originalPath;
if (!file_exists($mediaFullPath)) {
mkdir($mediaFullPath, 0775, true);
}
/* Check File is exist or not */
$fullFilepath = $mediaFullPath . $fileName;
if ($this->fileDriver->isExists($fullFilepath)) {
$fileName = rand() . time() . $fileName;
}
$fileContent = base64_decode($fileData['filecontent']);
$savedFile = fopen($mediaFullPath . $fileName, "wb");
fwrite($savedFile, $fileContent);
fclose($savedFile);
$uploadedFileName = "/" . $fileName ;
}
return $uploadedFileName;
}
}
And the VAR is :
$fileData is array
$fileData['filecontent'] = base64 string of file.
$fileData['name'] = file name.
Using base64 is the best solution.
Other solution: You can also get file data using file_get_contents() PHP function. And store in new file using file_put_contents() PHP function. This function creates an issue when data is large. When we use in graphql query then it returns only file data as a response.
Reference link :
https://www.w3schools.com/php/func_filesystem_file_get_contents.asp
https://www.w3schools.com/php/func_filesystem_file_put_contents.asp
https://www.php.net/manual/en/function.file-put-contents.php
Step 1: Create the directory structure for your module: app/code/XTeam/ImageUpload
Step 2: Create the file app/code/XTeam/ImageUpload/etc/schema.graphqls with the following content:
type Mutation {
xtUploadFiles(input: [ImageUploads!]): XTUploadOutput @resolver(class: "XTeam\\ImageUpload\\Model\\Resolver\\ImgUploadFiles") @doc(description:"Upload files to the pub/media static folder")
}
input ImageUploads {
image_url: String @doc(description: "Base64 encoded image string")
store_id: String @doc(description: "Store ID associated with the slider")
status: String @doc(description: "Status of the slider")
}
type XTUploadOutput {
items: [XTUploadedReturn]
}
type XTUploadedReturn {
order_path: String @doc(description: "File Order path")
message: String @doc(description: "Upload message")
}
Step 3: Create the file app/code/XTeam/ImageUpload/Model/Resolver/ImgUploadFiles.php with the following content:
<?php
declare(strict_types=1);
namespace XTeam\ImageUpload\Model\Resolver;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Filesystem;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use XTeam\Slider\Model\DataexampleFactory;
class ImgUploadFiles implements ResolverInterface
{
private $_storeManager;
private $fileSystem;
private $dataExampleFactory;
public function __construct(
\Magento\Store\Model\StoreManagerInterface $storeManager,
Filesystem $fileSystem,
DataexampleFactory $dataExampleFactory
) {
$this->_storeManager = $storeManager;
$this->fileSystem = $fileSystem;
$this->dataExampleFactory = $dataExampleFactory;
}
public function resolve(
Field $field,
$context,
ResolveInfo $info,
array $value = null,
array $args = null
) {
if (empty($args['input']) || !is_array($args['input'])) {
throw new GraphQlInputException(__('You must specify your input.'));
}
try {
$mediaUrl = $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$mediaPath = $this->fileSystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath();
$uploadPath = 'xteam/uploads/';
$mediaFullPath = $mediaPath . $uploadPath;
if (!file_exists($mediaFullPath)) {
mkdir($mediaFullPath, 0775, true);
}
$response = ['items' => []];
foreach ($args['input'] as $input) {
$base64Data = explode(',', $input['image_url']);
$fileContent = base64_decode(end($base64Data));
if ($fileContent === false) {
throw new GraphQlInputException(__('Invalid base64 encoded image.'));
}
$fileName = uniqid() . '.jpg';
$filePath = $mediaFullPath . $fileName;
file_put_contents($filePath, $fileContent);
$dataModel = $this->dataExampleFactory->create();
$dataModel->setData([
'image_url' => $mediaUrl . $uploadPath . $fileName,
'store_id' => $input['store_id'],
'status' => $input['status']
])->save();
$response['items'][] = [
'order_path' => $uploadPath . $fileName,
'message' => 'Image uploaded successfully.'
];
}
return $response;
} catch (InputException $e) {
throw new GraphQlInputException(__($e->getMessage()));
}
}
}
Step 4: Use the following GraphQL mutation:
mutation {
xtUploadFiles(
input: [
{
image_url: "data:image/jpeg;base64,[BASE64_ENCODED_IMAGE]",
store_id: "1",
status: "true"
}
]
) {
items {
order_path
message
}
}
}
Gives output like this:
{
"data": {
"xtUploadFiles": {
"items": [
{
"order_path": "xteam/uploads/unique_file_name.jpg",
"message": "Image uploaded successfully."
}
]
}
}
}