마 젠토 2 : UI Fileuploader 구현


22

나는 최근 에 Magento 2.1.7에서 내 양식으로 FileUploader Ui 구성 요소 를 구현했습니다 .

코드는 다음과 같습니다 ( app / code / Vendor / Blog / view / adminhtml / ui_component / vendor_blog_form.xml ).

<field name="featured_images">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" translate="true" xsi:type="string">Hervorgehobene Bilder:</item>
                    <item name="formElement" xsi:type="string">fileUploader</item>
                    <item name="componentType" xsi:type="string">fileUploader</item>
                    <item name="previewTmpl" xsi:type="string">Magento_Catalog/image-preview</item>
                    <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
                    <item name="allowedExtensions" xsi:type="string">jpg jpeg gif png</item>
                    <item name="notice" xsi:type="string" translate="true">Erlaubte Dateitypen: png, gif, jpg, jpeg.</item>
                    <item name="maxFileSize" xsi:type="number">2097152</item>
                    <item name="source" xsi:type="string">blog</item>
                    <item name="sortOrder" xsi:type="number">10</item>
                    <item name="dataScope" xsi:type="string">featured_images</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">false</item>
                    </item>
                    <item name="uploaderConfig" xsi:type="array">
                        <item name="url" xsi:type="url" path="vendor_blog/blog/upload"/>
                    </item>
                </item>
            </argument>
        </field>

내 컨트롤러는 이것입니다 ( app / code / Vendor / Blog / Controller / Adminhtml / Blog / Upload.php ) :

<?php

namespace Vendor\Blog\Controller\Adminhtml\Blog;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Backend\App\Action;  

class Upload extends \Vendor\Blog\Controller\Adminhtml\Blog
{

    protected $_fileUploaderFactory;
    protected $_directory_list;
    protected $_logger;

    public function __construct(
        Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory,
        \Magento\Framework\App\Filesystem\DirectoryList $directory_list,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->_fileUploaderFactory = $fileUploaderFactory;
        $this->_directory_list = $directory_list;
        $this->_logger = $logger;
        parent::__construct($context, $coreRegistry);
    }

    public function execute(){
        $uploader = $this->_fileUploaderFactory->create(['fileId' => 'featured_images']);
        $uploader->setAllowedExtensions(['jpg', 'jpeg', 'gif', 'png']);
        $uploader->setAllowRenameFiles(false);
        $uploader->setFilesDispersion(false);
        $path = $this->_filesystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath('blog');
        //$path = $this->_directory_list->getPath('media') . '/blog';
        $this->_logger->debug('Uploader.php: '.$path);
        $uploader->save($path);
    }
}

그러나 이미지를 업로드하고 Chrome 콘솔에서 호출을 검사하면 $ _FILES 배열이 비어있는 예외 500 오류 가 발생 합니다.

나는 이틀 동안 어려움을 겪고 있지만 제대로 작동하지는 않습니다. 대체 $path변수 행의 주석을 해제하면 업로드가 성공하지만 미리보기가 표시되지 않습니다.

나는 그것이 될 수 있음을 읽을 enctype문제를 일으키는 형태의,하지만 난 UI 구성 요소의 양식이를 확인하는 방법에 대한 정보를 찾을 수 없습니다.

전체 예외 코드가 필요한 경우 알려주십시오.

모든 도움을 주셔서 감사합니다. 고맙습니다!


왜 다른 업로드 방법을 시도하지 않습니까? 예를 들어. webkul.com/blog/…
Pallavi

슬프게도이 확장에 대해 XML 선언과 함께 순수 UI 구성 요소 만 사용하도록 제한되어 있습니다. 그러나 그것은 좋은 대안이 될 것입니다.
hallleron

답변:


35

이 단계에 따라 관리자 양식으로 UI fileuploader 구성 요소를 추가하십시오.

UI fileuploader 구성 요소를 사용하여 FAQ 확장 프로그램의 아이콘을 업로드합니다. https://github.com/mageprince/magento2-FAQ 에서 참조 할 수 있습니다

1) admin_form.xml(관리자 양식)에 필드 추가

<field name="icon">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="dataType" xsi:type="string">string</item>
            <item name="source" xsi:type="string">FaqGroup</item>
            <item name="label" xsi:type="string" translate="true">Group Image</item>
            <item name="visible" xsi:type="boolean">true</item>
            <item name="formElement" xsi:type="string">fileUploader</item>
            <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
            <item name="previewTmpl" xsi:type="string">Vendor_Module/image-preview</item>
            <item name="required" xsi:type="boolean">false</item>
            <item name="sortOrder" xsi:type="number">40</item>
            <item name="uploaderConfig" xsi:type="array">
                <item name="url" xsi:type="url" path="your_router/faqgroup/upload"/>
            </item>
        </item>
    </argument>
</field>

2) 이제 uploaderConfig관리자 형식으로 정의한 컨트롤러를 만들어야 합니다.<item name="url" xsi:type="url" path="vendor_module/faqgroup/upload"/>

app / code / Vendor / Module / Controller / Adminhtml / FaqGroup / Upload.php

<?php

namespace Vendor\Module\Controller\Adminhtml\FaqGroup;

use Magento\Framework\Controller\ResultFactory;

class Upload extends \Magento\Backend\App\Action
{
    public $imageUploader;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Vendor\Module\Model\ImageUploader $imageUploader
    ) {
        parent::__construct($context);
        $this->imageUploader = $imageUploader;
    }

    public function _isAllowed()
    {
        return $this->_authorization->isAllowed('Vendor_Module::Faq');
    }

    public function execute()
    {
        try {
            $result = $this->imageUploader->saveFileToTmpDir('icon');
            $result['cookie'] = [
                'name' => $this->_getSession()->getName(),
                'value' => $this->_getSession()->getSessionId(),
                'lifetime' => $this->_getSession()->getCookieLifetime(),
                'path' => $this->_getSession()->getCookiePath(),
                'domain' => $this->_getSession()->getCookieDomain(),
            ];
        } catch (\Exception $e) {
            $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }
        return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
    }
}

3) 생성 ImageUploader.php

앱 / 코드 / 공급 업체 / 모듈 / 모델 /ImageUploader.php

<?php

namespace Prince\Faq\Model;

class ImageUploader
{
    private $coreFileStorageDatabase;
    private $mediaDirectory;
    private $uploaderFactory;
    private $storeManager;
    private $logger;
    public $baseTmpPath;
    public $basePath;
    public $allowedExtensions;

    public function __construct(
        \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDatabase,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->coreFileStorageDatabase = $coreFileStorageDatabase;
        $this->mediaDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
        $this->uploaderFactory = $uploaderFactory;
        $this->storeManager = $storeManager;
        $this->logger = $logger;
        $this->baseTmpPath = "faq/tmp/icon";
        $this->basePath = "faq/icon";
        $this->allowedExtensions= ['jpg', 'jpeg', 'gif', 'png'];
    }

    public function setBaseTmpPath($baseTmpPath)
    {
        $this->baseTmpPath = $baseTmpPath;
    }

    public function setBasePath($basePath)
    {
        $this->basePath = $basePath;
    }

    public function setAllowedExtensions($allowedExtensions)
    {
        $this->allowedExtensions = $allowedExtensions;
    }

    public function getBaseTmpPath()
    {
        return $this->baseTmpPath;
    }

    public function getBasePath()
    {
        return $this->basePath;
    }

    public function getAllowedExtensions()
    {
        return $this->allowedExtensions;
    }

    public function getFilePath($path, $imageName)
    {
        return rtrim($path, '/') . '/' . ltrim($imageName, '/');
    }

    public function moveFileFromTmp($imageName)
    {
        $baseTmpPath = $this->getBaseTmpPath();
        $basePath = $this->getBasePath();
        $baseImagePath = $this->getFilePath($basePath, $imageName);
        $baseTmpImagePath = $this->getFilePath($baseTmpPath, $imageName);
        try {
            $this->coreFileStorageDatabase->copyFile(
                $baseTmpImagePath,
                $baseImagePath
            );
            $this->mediaDirectory->renameFile(
                $baseTmpImagePath,
                $baseImagePath
            );
        } catch (\Exception $e) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('Something went wrong while saving the file(s).')
            );
        }
        return $imageName;
    }

    public function saveFileToTmpDir($fileId)
    {
        $baseTmpPath = $this->getBaseTmpPath();
        $uploader = $this->uploaderFactory->create(['fileId' => $fileId]);
        $uploader->setAllowedExtensions($this->getAllowedExtensions());
        $uploader->setAllowRenameFiles(true);
        $result = $uploader->save($this->mediaDirectory->getAbsolutePath($baseTmpPath));
        if (!$result) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('File can not be saved to the destination folder.')
            );
        }

        $result['tmp_name'] = str_replace('\\', '/', $result['tmp_name']);
        $result['path'] = str_replace('\\', '/', $result['path']);
        $result['url'] = $this->storeManager
                ->getStore()
                ->getBaseUrl(
                    \Magento\Framework\UrlInterface::URL_TYPE_MEDIA
                ) . $this->getFilePath($baseTmpPath, $result['file']);
        $result['name'] = $result['file'];
        if (isset($result['file'])) {
            try {
                $relativePath = rtrim($baseTmpPath, '/') . '/' . ltrim($result['file'], '/');
                $this->coreFileStorageDatabase->saveFile($relativePath);
            } catch (\Exception $e) {
                $this->logger->critical($e);
                throw new \Magento\Framework\Exception\LocalizedException(
                    __('Something went wrong while saving the file(s).')
                );
            }
        }
        return $result;
    }
}

4) 생성 image-preview.html

app / code / Vendor / Module / view / adminhtml / web / template / image-preview.html

<div class="file-uploader-summary">
    <div class="file-uploader-preview">
        <a attr="href: $parent.getFilePreview($file)" target="_blank">
            <img
                class="preview-image"
                tabindex="0"
                event="load: $parent.onPreviewLoad.bind($parent)"
                attr="
                    src: $parent.getFilePreview($file),
                    alt: $file.name">
        </a>

        <div class="actions">
            <button
                type="button"
                class="action-remove"
                data-role="delete-button"
                attr="title: $t('Delete image')"
                click="$parent.removeFile.bind($parent, $file)">
                <span translate="'Delete image'"/>
            </button>
        </div>
    </div>

    <div class="file-uploader-filename" text="$file.name"/>
    <div class="file-uploader-meta">
        <text args="$file.previewWidth"/>x<text args="$file.previewHeight"/>
    </div>
</div>

5) 이제 ImageUploader.phpdi.xml 에 인수를 추가하십시오.

앱 / 코드 / 공급 업체 / 모듈 /etc/di.xml

<type name="Vendor\Module\Model\ImageUploader">
    <arguments>
        <!-- Temporary file stored in pub/media/faq/tmp/icon -->
        <argument name="baseTmpPath" xsi:type="string">faq/tmp/icon</argument>
        <argument name="basePath" xsi:type="string">faq/icon</argument>
        <argument name="allowedExtensions" xsi:type="array">
            <item name="jpg" xsi:type="string">jpg</item>
            <item name="jpeg" xsi:type="string">jpeg</item>
            <item name="gif" xsi:type="string">gif</item>
            <item name="png" xsi:type="string">png</item>
        </argument>
    </arguments>
</type>

이 파일에서 편집 양식에 업로드 된 이미지로드를 확인하십시오 : DataProvider.php

산출:

여기에 이미지 설명을 입력하십시오

데이터베이스에 이미지를 저장하려면

app / code / Vendor / Module / Controller / Adminhtml / Save.php

<?php

namespace Vendor\Module\Controller\Adminhtml;

use Magento\Framework\Exception\LocalizedException;

class Save extends \Magento\Backend\App\Action
{
    protected $dataPersistor;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\App\Request\DataPersistorInterface $dataPersistor
    ) {
        $this->dataPersistor = $dataPersistor;
        parent::__construct($context);
    }

    public function execute()
    {
        ...
        ...
        $data = $this->_filterFoodData($data);
        $model->setData($data);
        $model->save();
        ...
        ...     
    }

    public function _filterFoodData(array $rawData)
    {
        //Replace icon with fileuploader field name
        $data = $rawData;
        if (isset($data['icon'][0]['name'])) {
            $data['icon'] = $data['icon'][0]['name'];
        } else {
            $data['icon'] = null;
        }
        return $data;
    }
}

업로드 한 이미지를 양식 편집 페이지에 표시하려면

app / code / Vendor / Module / Model / DataProvider.php

<?php

namespace Vendor\Module\Model;

use Magento\Store\Model\StoreManagerInterface;

class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
    ...
    ...

    public function getData()
    {
        ...
        ...
        $items = $this->collection->getItems();

        //Replace icon with fileuploader field name
        foreach ($items as $model) {
            $this->loadedData[$model->getId()] = $model->getData();
            if ($model->getIcon()) {
                $m['icon'][0]['name'] = $model->getIcon();
                $m['icon'][0]['url'] = $this->getMediaUrl().$model->getIcon();
                $fullData = $this->loadedData;
                $this->loadedData[$model->getId()] = array_merge($fullData[$model->getId()], $m);
            }
        }
        ...
        ...

        return $this->loadedData;
    }

    public function getMediaUrl()
    {
        $mediaUrl = $this->storeManager->getStore()
            ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA).'faq/tmp/icon/';
        return $mediaUrl;
    }
}

정말 감사합니다. 정말 감사합니다. 그러나 솔루션을 구현하고 이미지를 업로드 할 때 Chrome 콘솔에서 반환되는 응답은 { "error": "$ _ FILES array is empty", "errorcode": 0}입니다. 파일이 업로드되지 않았으며 (chmod를 확인했습니다) 물론 미리보기가 표시되지 않습니다.
hallleron

1
실제로 코드의 도움으로 마침내 작동했습니다. 정말 고마워요! 너는 나의 영웅이야! :-)
hallleron

가장 환영합니다 :)
Prince Patel

@PrincePatel이 그냥 중대하다,하지만 난 편집 양식을 가지고 가정, 내가 어떻게 이미지 미리보기 템플릿 데이터 공급자에서 GetData의에서 읽을 수 있습니다
Yehia A.Salam에게

1
@PrincePatel Magento 2.3에서 일하고 있으며 di.xml에서 "ImageUploader"를 호출하고 같은 곳에서 baseTmpPath, basePath 및 allowedExtensions 매개 변수를 보냅니다. 이제 모델 "ImageUploader"에서 "Exception # 0 (BadMethodCallException) : 필수 인수 $ baseTmpPath 누락"오류가 발생합니다. "ImageUploader"모델의 생성자 함수에서 정적으로 설정되는 대신 di.xml에서 관리하는 방법을 알려주시겠습니까?
Dhara Bhatti

6

Magento 2.2 UI 구성 요소 보충

Magento 2.2의 Magento 2.1과 비교 하면 UI 구성 요소 에는 다음과 같은 선택적 차이 가 있습니다. 우리는 공식 Magento_Catalog/image-preview을 미리보기 사원 으로 사용할 수 있으며 컨트롤러와 같은 나머지 코드는 허용되는 답변을 참조 할 수 있습니다.

<field name="image" formElement="fileUploader">
    <settings>
        <notice translate="true">Allowed file types: jpg, jpeg, gif, png.</notice>
        <label translate="true">Image</label>
        <componentType>fileUploader</componentType>
    </settings>
    <formElements>
        <fileUploader>
            <settings>
                <allowedExtensions>jpg jpeg gif png</allowedExtensions>
                <maxFileSize>10240000</maxFileSize>
                <placeholderType>image</placeholderType>
                <previewTmpl>Magento_Catalog/image-preview</previewTmpl>
                <uploaderConfig>
                    <param xsi:type="string" name="url">path/to/controller</param>
                </uploaderConfig>
            </settings>
        </fileUploader>
    </formElements>
</field>

1
오류가 발생 TypeError: value.map is not a function합니다. 수정 방법
Nero Phung

@NeroPhung 안녕하세요,이 솔루션을 사용해보십시오 magento.stackexchange.com/q/138642/44237
Key Shang

나는 그 게시물을 따르는 내 자신에 의해이 문제를 수행했습니다. 도와 주셔서 감사합니다!
Nero Phung

@KeyShang, 코드에서, 이미지 업 로더 필드에 대한 유효성 검증 방법 및 위치
Jaisa

@ 스리랑카 나는 당신의 질문을보고, 나는 당신의 질문에 대답 할 것입니다 .magento.stackexchange.com / questions / 211957 /…
키 샹
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.