【问题标题】:jQuery iframe file uploadjQuery iframe 文件上传
【发布时间】:2011-12-16 02:05:29
【问题描述】:

我正在使用 jQuery 构建文件上传,但在尝试设置表单属性时遇到 jQuery 错误:

$(document).ready(function () {
    $("#formsubmit").click(function () {

        var iframe = $('<iframe name="postframe" id="postframe" class="hidden" src="about:none" />');

        $('div#iframe').append(iframe);

        $('#theuploadform').attr("action", "/ajax/user.asmx/Upload")
        $('#theuploadform').attr("method", "post")
        $('#theuploadform').attr("userfile", $('#userfile').val())
        $('#theuploadform').attr("enctype", "multipart/form-data")
        $('#theuploadform').attr("encoding", "multipart/form-data")
        $('#theuploadform').attr("target", "postframe")
        $('#theuploadform').submit();
        //need to get contents of the iframe

        $("#postframe").load(
            function () {
                iframeContents = $("iframe")[0].contentDocument.body.innerHTML;
                $("div#textarea").html(iframeContents);
            }
        );
    }
);


<div id="uploadform">
    <form id="theuploadform" action="">
        <input id="userfile" name="userfile" size="50" type="file" />
        <input id="formsubmit" type="submit" value="Send File" />
    </form>
</div>

<div id="iframe" style="width: 0px; height: 0px; display: none;">
</div>

<div id="textarea">
</div>

【问题讨论】:

  • 这一行的目的是什么? $('#theuploadform').attr("userfile", $('#userfile').val()) 由于安全原因,浏览器实际上无法访问文件输入的值,它会返回一些虚假路径。
  • 你错了,你可以读取值,但不能改变它。
  • 返回值是什么?我确实说过它会返回一个值,而不是文件的实际路径。

标签: javascript jquery


【解决方案1】:

我找到了解决方案。此代码有效:

<script type="text/javascript">

    $(document).ready(function () {

        $("#formsubmit").click(function () {

            var iframe = $('<iframe name="postiframe" id="postiframe" style="display: none"></iframe>');

            $("body").append(iframe);

            var form = $('#theuploadform');
            form.attr("action", "/upload.aspx");
            form.attr("method", "post");

            form.attr("encoding", "multipart/form-data");
            form.attr("enctype", "multipart/form-data");

            form.attr("target", "postiframe");
            form.attr("file", $('#userfile').val());
            form.submit();

            $("#postiframe").load(function () {
                iframeContents = this.contentWindow.document.body.innerHTML;
                $("#textarea").html(iframeContents);
            });

            return false;

        });

    });

</script>


<form id="theuploadform">
    <input id="userfile" name="userfile" size="50" type="file" />
    <input id="formsubmit" type="submit" value="Send File" />
</form>

<div id="textarea">
</div>

【讨论】:

  • 非常感谢我花了很长时间试图解决它,对于那些现在可能找到它的人,请注意你应该使用 e.preventDefault 而不是返回 false 并在函数开始时删除 iFrame如果它存在,如果您打算使用此上传多个文件
  • 谢谢你,简单的代码,做的工作,比我读过的所有教程都好!
  • 似乎 form.attr("file", $('#userfile').val()) 没有做任何事情。它包含文件的名称,但由浏览器自动发布。
  • 对于复制此代码的人 - iframe 应该有一个结束标记,它不是自动关闭的,尽管它在某些浏览器中可能会这样工作。
  • 为了完整起见,只有在同一个域中访问 iframe 的内容时,才能读取 iframe 的内容。其他域会抛出安全错误
【解决方案2】:

这不是官方插件,但这里有一个示例,说明如何将表单的提交逻辑包装到插件中。

例子:

<form method="post" enctype="multipart/form-data">
    <input name="file" type="file" />

    <input type="text" name="test" />

    <button type="submit">Submit</button>
</form>

<script>
    $('form').submit(function (e) {

        //prevent default submit
        e.preventDefault();

        //submit through frame
        $(this).frameSubmit({
            done: function (form, frame, options) {
                console.log('done!');
            },
            fail: function (form, frame, options) {
                console.log('fail!');
            },
            always: function (form, frame, options) {
                console.log('always!');
            }

            //custom hasError implementation if needed
            //by default if the frame's body HTML contains the text "unexpected error" or "server error"
            //it is treated as an error
            /*,hasError: function (frame) {
                return false;
            }*/
        });
    });

</script>

插件

!function ($, doc) {
    var _frameCount = 0,
        _callbackOptions = ['done', 'fail', 'always'],
        _hasFailed = function (frame) {
            var frameHtml = $(frame).contents().find('body').html();

            return /(server|unexpected)\s+error/i.test(frameHtml);
        },
        _createFrame = function () {
            return $('<iframe>').prop('name', 'jq-frame-submit-' + _frameCount++).hide().appendTo(doc.body);
        };

    $.fn.extend({
        frameSubmit: function (options) {

            return this.each(function () {
                var deferred = $.Deferred(),
                    form = this,
                    initialTarget = form.target,
                    hasTarget = form.hasAttribute('target'),
                    hasFailed = options.hasFailed || _hasFailed,

                    //The initial frame load will fire a load event so we need to
                    //wait until it fires and then submit the form in order to monitor
                    //the form's submission state.
                    $frame = _createFrame().one('load', function () {
                        $frame.one('load', function () {
                            deferred[hasFailed(this) ? 'reject' : 'resolve'](form, this, options);
                            $frame.remove();
                        });

                        form.submit();

                        //restore initial target attribute's value
                        if (hasTarget) form.target = initialTarget;
                        else form.removeAttribute('target');
                    });

                //attach handlers to the deferred
                $.each(_callbackOptions, function (i, optName) {
                    options[optName] && deferred[optName](options[optName]);
                });

                //make sure the form gets posted the to iframe
                form.target = $frame.prop('name');
            });
        }
    });
}(jQuery, document);

【讨论】:

    【解决方案3】:

    您的表单目标应与 iframe 名称相同,例如:

    <form target="frame" 
          action="http://posttestserver.com/post.php?dir=example" 
          method="post"
          enctype="multipart/form-data">
        <input name="file" type="file"/>
    </form>
    
    <iframe name="frame"></iframe>
    

    在此之后,您可以将事件附加到输入按钮以侦听“更改”。 此外,您可以使用 jsonp 从服务器获取进度,所有这些都可以在任何浏览器事件 IE3+ 中运行。像这样的:

    $('input').change(function () {
        $('form').submit();
    });
    
    $.getJSON('/echo/jsonp/?callback=?', function(e, progress) {
        console.log(progress);
    });
    

    【讨论】:

      【解决方案4】:

      这是一个使用ajax上传文件的好插件

      http://jquery.malsup.com/form/#file-upload

      【讨论】:

        【解决方案5】:

        您知道,与其多次获取同一个项目,不如直接重复使用它:

        var form = $('#theuploadform');
        form.attr("action", "/ajax/user.asmx/Upload");
        form.attr("method", "post");
        // and so on
        

        您遇到了什么样的错误?可以发一下吗?

        更新

        由于您无法在此处自行设置属性,因此可以解决:

        将表单放入 iframe 中,并将 onchange 事件附加到输入按钮。 当用户选择文件时,触发上传文件(提交)所需的代码,然后父窗口可以关闭 iframe。

        【讨论】:

        • 这很简单,不要让我设置 attr 用户文件。
        猜你喜欢
        • 2014-08-13
        • 1970-01-01
        • 2012-07-07
        • 1970-01-01
        • 2016-02-13
        • 2012-02-22
        • 2011-08-20
        • 1970-01-01
        • 2015-12-01
        相关资源
        最近更新 更多