Question

In my custom form I use the file uploader element:

<field name="image">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string">Image</item>
            <item name="visible" xsi:type="boolean">true</item>
            <item name="formElement" xsi:type="string">fileUploader</item>
            <item name="allowedExtensions" xsi:type="string">jpg jpeg gif png svg</item>
            <item name="maxFileSize" xsi:type="number">20000000</item>
            <item name="uploaderConfig" xsi:type="array">
                <item name="url" xsi:type="url" path="path/to/imageUpload"/>
            </item>
        </item>
    </argument>
</field>

It works fine in the Chrome & FireFox, but in the Safari it throws an error:

TypeError: postData.data.set is not a function. (In ‘postData.data.set(‘param_name’, this.paramName)‘, ‘postData.data.set’ is undefined)

file-uploader.js:307

Investigating the code I have found that all is ok in the Magento 2.1.8 (in my opinion):

    /**
     * Handler which is invoked prior to the start of a file upload.
     *
     * @param {Event} e - Event obejct.
     * @param {Object} data - File data that will be uploaded.
     */
    onBeforeFileUpload: function (e, data) {
        var file     = data.files[0],
            allowed  = this.isFileAllowed(file),
            target   = $(e.target);

        if (allowed.passed) {
            target.on('fileuploadsend', function (event, postData) {
/** Line 307 */ postData.data.set('param_name', this.paramName);
                $(event.currentTarget).off('fileuploadsend');
            }.bind(data));

            target.fileupload('process', data).done(function () {
                data.submit();
            });
        } else {
            this.notifyError(allowed.message);
        }
    },

But code in the Magento 2.1.7 looks different, and it does not use the FormData.set method directly:

    /**
     * Handler which is invoked prior to the start of a file upload.
     *
     * @param {Event} e - Event obejct.
     * @param {Object} data - File data that will be uploaded.
     */
    onBeforeFileUpload: function (e, data) {
        var file     = data.files[0],
            allowed  = this.isFileAllowed(file);

        if (allowed.passed) {
            $(e.target).fileupload('process', data).done(function () {
                data.submit();
            });
        } else {
            this.notifyError(allowed.message);
        }
    },

Then I have found a similar bug report on the github:

https://github.com/magento/magento2/issues/10520

Unfortunately it has been closed by magento team without an any information.

Future investigation leaded me to the developer.mozilla.org page where I have found interesting information: they say that Safari does not supports the FormData.set method at all:

developer.mozilla.org FormData.set method description

So question is: how in this case it can be used in the core magento? Is any known workaround for this error or I missed something?

PS: Tested in the Content > Design > Configuration > Header > Upload Logo and the standard file uploader does not works too - throwing the same error.

PPS: Safari Version 10.1.2 (12603.3.8)

PPPS: I have found the similar question on the StackOverflow (not in Magento context), but it has been asked more than year ago...

Was it helpful?

Solution

This is a magento bug after version 2.1.8 and it is fixed in the Magento 2.2.0. Here is updated code:

    /**
     * Handler which is invoked prior to the start of a file upload.
     *
     * @param {Event} e - Event object.
     * @param {Object} data - File data that will be uploaded.
     */
    onBeforeFileUpload: function (e, data) {
        var file     = data.files[0],
            allowed  = this.isFileAllowed(file),
            target   = $(e.target);

        if (allowed.passed) {
            target.on('fileuploadsend', function (event, postData) {
                postData.data.append('param_name', this.paramName);
            }.bind(data));

            target.fileupload('process', data).done(function () {
                data.submit();
            });
        } else {
            this.notifyError(allowed.message);
        }
    },

as you can see now Magento use the method postData.data.append which doe not throws errors in the Safari.

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