Question

I know this has been asked before but have not seen any answer for Magento2 I have a Magento2.4 website and I want to when creating a cms page be able to upload and insert into the page a link to a pdf as well as be able to insert a svg based image. Currently both those file types are blocked.

I created a module I call Customfileuploads and in the modules etc/di.xml file I have the below however it does not seem to work when I try to then add a svg to the file manager in the admin panel.

 <?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
   
    <type name="Magento\Cms\Model\Wysiwyg\Images\Storage">
        <arguments>
            <argument name="extensions" xsi:type="array">
                <item name="allowed" xsi:type="array">
                    <item name="jpg" xsi:type="string">image/jpg</item>
                    <item name="jpeg" xsi:type="string">image/jpeg</item>
                    <item name="png" xsi:type="string">image/png</item>
                    <item name="gif" xsi:type="string">image/gif</item>
                    <item name="svg" xsi:type="string">text/html</item>
                </item>
                <item name="image_allowed" xsi:type="array">
                    <item name="jpg" xsi:type="string">image/jpg</item>
                    <item name="jpeg" xsi:type="string">image/jpeg</item>
                    <item name="png" xsi:type="string">image/png</item>
                    <item name="gif" xsi:type="string">image/gif</item>
                    <item name="svg" xsi:type="string">text/html</item>
                </item>
                <item name="media_allowed" xsi:type="array">
                    <item name="flv" xsi:type="string">video/x-flv</item>
                    <item name="avi" xsi:type="string">video/x-msvideo</item>
                    <item name="mov" xsi:type="string">video/x-sgi-movie</item>
                    <item name="rm" xsi:type="string">application/vnd.rn-realmedia</item>
                    <item name="wmv" xsi:type="string">video/x-ms-wmv</item>
                    <item name="svg" xsi:type="string">text/html</item>
                </item>
            </argument>
         
        </arguments>
    </type>
</config>
Was it helpful?

Solution

I have written a solution that is code focused

 <?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Cms\Model\Wysiwyg\Images\Storage">
        <arguments>
            <argument name="extensions" xsi:type="array">
                <item name="allowed" xsi:type="array">
                    <item name="svg" xsi:type="string">image/svg</item>
                    <item name="pdf" xsi:type="string">application/pdf</item>
                </item>
                <item name="image_allowed" xsi:type="array">
                    <item name="svg" xsi:type="string">image/svg+xml</item>
                    <item name="pdf" xsi:type="string">application/pdf</item>
                </item>
                <item name="media_allowed" xsi:type="array">
                    <item name="svg" xsi:type="string">image/svg+xml</item>
                    <item name="pdf" xsi:type="string">application/pdf</item>
                </item>
            </argument>
        </arguments>

        <plugin name="bypass_svg_filter" type="Mbs\SavAndPdf\Plugin\ImageStorageValidation" />
    </type>

    <preference for="Magento\MediaStorage\Model\File\Uploader" type="Mbs\SavAndPdf\Model\FileUploader" />
</config>

one plugin:

<?php

namespace Mbs\SavAndPdf\Plugin;

use Magento\Cms\Model\Wysiwyg\Images\Storage;
use Magento\Framework\App\Filesystem\DirectoryList;

class ImageStorageValidation
{
    /**
     * @var \Magento\Framework\Filesystem\Directory\Write
     */
    private $_directory;
    /**
     * @var \Magento\Framework\Filesystem\Io\File
     */
    private $ioFile;

    public function __construct(
        \Magento\Framework\Filesystem $filesystem,
        \Magento\Framework\Filesystem\Io\File $file
    ) {
        $this->_directory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
        $this->ioFile = $file;
    }

    public function beforeUploadFile(
        Storage $subject,
        $targetPath,
        $type
    ) {
        if (is_null($type)) {
            $type = 'image';
        }

        return [
            $targetPath,
            $type
        ];
    }

    public function aroundResizeFile(
        Storage $subject,
        callable $proceed,
        $source,
        $keepRatio = true
    ) {
        if (strpos($source, '.svg')===false
            && strpos($source, '.pdf')===false
        ) {
            $result = $proceed($source, $keepRatio);
            return $result;
        }

        return false;
    }
}

one preference:

<?php

namespace Mbs\SavAndPdf\Model;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\File\Mime;

class FileUploader extends \Magento\MediaStorage\Model\File\Uploader
{
    /**
     * @var \Magento\Framework\File\Mime
     */
    private $fileMime;

    public function __construct(
        $fileId,
        \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDb,
        \Magento\MediaStorage\Helper\File\Storage $coreFileStorage,
        \Magento\MediaStorage\Model\File\Validator\NotProtectedExtension $validator,
        \Magento\Framework\File\Mime $fileMime
    ) {
        parent::__construct($fileId, $coreFileStorageDb, $coreFileStorage, $validator);
        $this->fileMime = $fileMime;
    }

    /**
     * Return file mime type
     *
     * @return string
     */
    private function _getMimeType()
    {
        return $this->fileMime->getMimeType($this->_file['tmp_name']);
    }

    /**
     * Used to check if uploaded file mime type is valid or not
     *
     * @param string[] $validTypes
     * @access public
     * @return bool
     */
    public function checkMimeType($validTypes = [])
    {
        if (count($validTypes) > 0) {
            if (!in_array($this->_getMimeType(), $validTypes)) {
                return $this->fallbackOnSvgFilter($validTypes);
            }
        }
        return true;
    }

    private function fallbackOnSvgFilter($validTypes)
    {
        if (strpos($this->_getMimeType(), 'svg')!== false) {
            foreach ($validTypes as $validType) {
                if (strpos($validType, 'svg')!==false) {
                    return true;
                }
            }
        }

        if (strpos($this->_getMimeType(), 'pdf')!== false) {
            foreach ($validTypes as $validType) {
                if (strpos($validType, 'pdf')!==false) {
                    return true;
                }
            }
        }

        return false;
    }
}

It is not perfect and I do appreciate for 250 points you want something pristine. But its advantage is that is should be quite easy for you to understand and adjust to your needs.

Many thanks for pushing us to the next level, feeling exhausted now!

also, I put the link to the full repository: https://bitbucket.org/magstaging/savandpdf/src/master/

OTHER TIPS

If you are using Magento 2.4 then you can add code like this :

app/code/Vendor/Extension/etc/di.xml

<type name="Magento\Cms\Model\Wysiwyg\Images\Storage">
<arguments>
    <argument name="extensions" xsi:type="array">
        <item name="allowed" xsi:type="array">
            <item name="svg" xsi:type="string">image/svg+xml</item>
            <item name="pdf" xsi:type="string">application/pdf</item>   
        </item>
        <item name="image_allowed" xsi:type="array">
            <item name="svg" xsi:type="string">image/svg+xml</item>
            <item name="pdf" xsi:type="string">application/pdf</item>
        </item>
        <item name="media_allowed" xsi:type="array">
            <item name="svg" xsi:type="string">image/svg+xml</item>
            <item name="pdf" xsi:type="string">application/pdf</item>
        </item>
    </argument>
</arguments>

And added this code into module.xml

app/code/Vendor/Extension/etc/module.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_Extension">
        <sequence>
            <module name="Magento_Cms"/>
        </sequence>
    </module>
</config>

This is a good question, it often comes up in different contexts.

It seems svg files are added as protected extensions. I only managed to upload svg file after I override that config.xml like this:

app/code/StackExchange/Wysiwyg/etc/config.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <general>
            <file>
                <protected_extensions>
                    <svg>0</svg>
                </protected_extensions>
            </file>
        </general>
    </default>
</config>

You might also need to have like this is in module.xml to make sure it overrides the config value:

app/code/StackExchange/Wysiwyg/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="StackExchange_Wysiwyg" setup_version="0.1.0">
        <sequence>
            <module name="Magento_MediaStorage"/>
        </sequence>
    </module>
</config>

app/code/StackExchange/Wysiwyg/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"
>
    <type name="Magento\Cms\Model\Wysiwyg\Images\Storage">
        <arguments>
            <argument name="extensions" xsi:type="array">
                <item name="allowed" xsi:type="array">
                    <item name="svg" xsi:type="string">image/svg</item>
                    <item name="pdf" xsi:type="string">application/pdf</item>
                </item>
                <item name="image_allowed" xsi:type="array">
                    <item name="svg" xsi:type="string">image/svg</item>
                    <item name="pdf" xsi:type="string">application/pdf</item>
                </item>
                <item name="media_allowed" xsi:type="array">
                    <item name="svg" xsi:type="string">image/svg</item>
                    <item name="pdf" xsi:type="string">application/pdf</item>
                </item>
            </argument>
        </arguments>
    </type>
</config>

I am not sure if the mime type is different for different svg-files or not. First I tried with image/svg+xml, then I debugged the code and it turned out my svg file had the mime-type image/svg. So if this does not work you might consider setting a break point in:

\Magento\Framework\File\Uploader::checkMimeType

and check the value of $this→_getMimeType() when you upload the file.

Furthermore you will get some errors when you upload the files like:

enter image description here

However, the files are still uploaded. The error is thrown by the imagick module that it can not create a thumbnail and resize the photo. Fortunately it works fine and shows in the storefront.

About the pdf, using this technique they will be uploaded using the image uploader and shown in the list of images. When you select them you will get an image html tag referring to them, this tag you will manually have to change to a link tag.

Here is a solution for uploading SVG images: https://github.com/MagestyApps/module-web-images

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top