Firefox从iframe上传文件时出现NS_ERROR_UNEXPECTED

NS_ERROR_UNEXPECTED in Firefox when uploading file from iframe

本文关键字:NS ERROR UNEXPECTED iframe 文件 Firefox      更新时间:2023-09-26

我试图允许用户上传文件而不会导致页面在上传文件时发生变化。为此,我使用iframe,向其添加表单和文件输入,然后在(隐藏的)iframe中提交表单。这在Chrome上运行良好,但在Firefox上不行。

下面是导致这个问题的代码。

<!DOCTYPE html>
<html>
    <head>
        <style>
            #pretty-button { background: blue; }
            #hidden-uploader { display: none; }
        </style>
        <script>
        window.addEventListener('DOMContentLoaded', function() {
            var btn = document.getElementById('pretty-button');
            var filename_output = document.getElementById('filename');
            var upload_iframe = document.getElementById('hidden-uploader');
            btn.addEventListener('click', function() {
                document.body.appendChild(upload_iframe);
                _document = upload_iframe.contentDocument;
                var form = _document.createElement('form');
                form.setAttribute('method', 'post');
                form.setAttribute('enctype', 'multipart/form-data');
                form.setAttribute('action', '.');
                var file_input = _document.createElement('input');
                file_input.setAttribute('type', 'file');
                file_input.setAttribute('name', 'document');
                form.appendChild(file_input);
                _document.body.appendChild(form);
                file_input.click();
                file_input.addEventListener('change', function() {
                    console.log('file selected');
                    form.submit();
                    upload_iframe.addEventListener('load', function() {
                        console.log('file uploaded');
                    });
                });
            });
        });
        </script>
    </head>
    <body>
        <button id="pretty-button">Choose a File</button>
        <span id="filename"></span>
        <iframe id="hidden-uploader"></iframe>
    </body>
</html>

在firefox上,当选择文件时,在第33行NS_ERROR_UNEXPECTED:(即form.submit())上失败。

你知道这里可能发生了什么吗?

我想我找到问题了,在

document.body.appendChild(upload_iframe);

这会导致iframe重新加载自己,这意味着iframe的contentDocument在重新附加到文档主体之前与重新附加到文档主体之后的contentDocument不同。重新加载发生在文件对话框打开时。

这可以通过以下更改来验证:

<!DOCTYPE html>
<html>
    <head>
        <style>
            #pretty-button { background: blue; }
            #hidden-uploader { display: none; }
        </style>
        <script>
        window.addEventListener('DOMContentLoaded', function() {
            var btn = document.getElementById('pretty-button');
            var filename_output = document.getElementById('filename');
            var upload_iframe = document.getElementById('hidden-uploader');
            btn.addEventListener('click', function() {
                document.body.appendChild(upload_iframe);
                _document = upload_iframe.contentDocument;
                var form = _document.createElement('form');
                form.setAttribute('method', 'post');
                form.setAttribute('enctype', 'multipart/form-data');
                form.setAttribute('action', '.');
                var file_input = _document.createElement('input');
                file_input.setAttribute('type', 'file');
                file_input.setAttribute('name', 'document');
                form.appendChild(file_input);
                _document.body.appendChild(form);
                file_input.click();
                // So far, the iframe hasn't reloaded.
                file_input.addEventListener('change', function() {
                    /* Because the iframe loads in less time than it 
                     * takes for the user to select a file, the iframe
                     * has now reloaded, and _document refers to the 
                     * contentDocument of an iframe which is no longer
                     * attached to the page.
                     */
                    console.log('file selected');
                    var _newDocument = upload_iframe.contentDocument;
                    console.log(_document === _newDocument); // false in Firefox, true in Chrome
                    form.submit();
                    upload_iframe.addEventListener('load', function() {
                        console.log('file uploaded');
                    });
                });
            });
        });
        </script>
    </head>
    <body>
        <button id="pretty-button">Choose a File</button>
        <span id="filename"></span>
        <iframe id="hidden-uploader"></iframe>
    </body>
</html>

通过删除违规行,上面的代码开始在Firefox中工作。