Magento 2: Triển khai trình tải lên tệp UI


21

Gần đây tôi đã triển khai Thành phần Ui FileUploader trong mẫu của mình trên Magento 2.1.7.

Mã cho nó ở đây ( app / code / Vendor / Blog / view / adminhtml / ui_component / eller_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>

Trình điều khiển của tôi cho nó là cái này ( ứng dụng / mã / Nhà cung cấp / Blog / Trình điều khiển / 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);
    }
}

Tuy nhiên, khi tôi tải lên một hình ảnh và kiểm tra cuộc gọi trong bảng điều khiển của Chrome, tôi nhận được Lỗi 500 với Ngoại lệ: mảng $ _FILES trống .

Tôi đang vật lộn trong hai ngày nhưng tôi không thể làm cho nó hoạt động tốt. Khi tôi bỏ ghi chú dòng $pathbiến thay thế , Tải lên thành công nhưng tôi không nhận được bản xem trước.

Tôi đọc được rằng đó có thể là enctypehình thức gây ra sự cố, nhưng tôi không tìm thấy bất kỳ thông tin nào về cách kiểm tra điều này đối với biểu mẫu Thành phần UI.

Nếu bạn cần toàn bộ mã ngoại lệ xin vui lòng cho tôi biết.

Tôi đánh giá cao mọi sự giúp đỡ có thể. Cảm ơn bạn!


Tại sao bạn không thử một cách tải lên khác? ví dụ webkul.com/blog/ từ
Pallavi

Đáng buồn là tôi bị giới hạn chỉ sử dụng các Thành phần UI thuần túy với khai báo XML cho tiện ích mở rộng này. Nhưng nó sẽ là một thay thế tốt đẹp mặc dù.
hallleron

Câu trả lời:


35

Tôi làm theo các bước này để thêm thành phần trình tải lên tệp UI trong mẫu quản trị viên

Tôi sử dụng thành phần tải lên tệp UI để tải lên một biểu tượng cho tiện ích mở rộng Câu hỏi thường gặp của mình. Bạn có thể tham khảo từ đây: https://github.com/mageprince/magento2-FAQ

1) Thêm trường trong admin_form.xml(Mẫu quản trị)

<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) Bây giờ chúng ta cần tạo bộ điều khiển mà chúng ta xác định trong uploaderConfigmẫu quản trị viên:<item name="url" xsi:type="url" path="vendor_module/faqgroup/upload"/>

ứng dụng / mã / Nhà cung cấp / Mô-đun / Trình điều khiển / 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) Tạo ImageUploader.php

ứng dụng / mã / Nhà cung cấp / Mô-đun / Mô hình / 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) Tạo image-preview.html

ứng dụng / mã / Nhà cung cấp / Mô-đun / lượt xem / 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) Bây giờ thêm đối số cho ImageUploader.phptrong di.xml

ứng dụng / mã / Nhà cung cấp / Mô-đun / 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>

Kiểm tra tệp này để tải hình ảnh được tải lên ở dạng chỉnh sửa: DataProvider.php

ĐẦU RA:

nhập mô tả hình ảnh ở đây

Để lưu hình ảnh trong cơ sở dữ liệu

ứng dụng / mã / Nhà cung cấp / Mô-đun / Trình điều khiển / 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;
    }
}

Để hiển thị hình ảnh được tải lên trong trang chỉnh sửa biểu mẫu:

ứng dụng / mã / Nhà cung cấp / Mô-đun / Mô hình / 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;
    }
}

Cảm ơn bạn rất nhiều vì điều này, thực sự đánh giá cao nó. Tuy nhiên, khi tôi triển khai giải pháp của bạn và tải lên một Hình ảnh, phản hồi được trả về của tôi trong bảng điều khiển của Chrome là: {"error": "$ _ Mảng FILES trống", "errorcode": 0}. Các tập tin chưa được tải lên (tôi đã kiểm tra chmod) và tất nhiên bản xem trước không thể hiển thị.
hallleron

1
Trên thực tế tôi đã làm cho nó hoạt động cuối cùng với sự giúp đỡ của mã của bạn. Cảm ơn bạn rất nhiều! Bạn là người hùng của tôi! :-)
hallleron

Bạn được chào đón nhất :)
Hoàng tử Patel

@PrincePatel điều này thật tuyệt, nhưng giả sử tôi có một mẫu chỉnh sửa, làm cách nào tôi có thể tạo mẫu xem trước hình ảnh được đọc từ getData từ nhà cung cấp dữ liệu
Yehia A.Salam

1
@PrincePatel Tôi đang làm việc trong Magento 2.3 và gọi "ImageUploader" từ di.xml và gửi các thông số baseTmpPath, basePath và allowExtensions từ cùng. Bây giờ mô hình "ImageUploader" của tôi đưa ra lỗi "Ngoại lệ # 0 (BadMethodCallException): Thiếu đối số bắt buộc $ baseTmpPath". Bạn có thể vui lòng giúp tôi cách quản lý từ di.xml thay vì được đặt tĩnh trong hàm xây dựng của mô hình "ImageUploader" không?
Dhara Bhatti

6

Bổ sung cho thành phần UI Magento 2.2

So sánh với Magento 2.1, trong Magento 2.2 , thành phần UI có một số khác biệt tùy chọn như bên dưới. Chúng tôi có thể sử dụng chính thức Magento_Catalog/image-previewlàm templete xem trước và phần còn lại của các mã như bộ điều khiển có thể tham khảo câu trả lời được chấp nhận .

<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
Tôi nhận được lỗi TypeError: value.map is not a function. Làm cách nào tôi có thể sửa nó
Nero Phung

@NeroPhung Xin chào, vui lòng thử giải pháp này magento.stackexchange.com/q/138642/44237
Key Shang

Tôi đã thực hiện vấn đề này một mình trong khi theo dõi bài viết đó. Cảm ơn về sự hỗ trợ!
Nero Phụng

@KeyShang, Trong mã của bạn, Làm thế nào và ở đâu Tôi đặt xác thực cho trường trình nâng cấp hình ảnh
Jaisa

@Sri Tôi thấy câu hỏi của bạn, tôi sẽ trả lời nó trong câu hỏi của bạn magento.stackexchange.com/questions/211957/ , hãy cho tôi một chút thời gian.
Key Shang
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.