简体   繁体   中英

jQuery iframe file upload

Im building a file upload with jQuery, but Im getting a jQuery error trying to set the attributes of the form:

$(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>

I found the solution. This code works:

<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>

It's not an official plugin, however here's an example on how you could wrap the form's submitting logic into a plugin.

Example:

<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>

PLUGIN

!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);

Your form target should be the same as iframe name, for example:

<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>

And after this you can attach event to input button to listen for 'change'. Furthemore you can get progress from server using jsonp and all of this will work in any browser event IE3+. Something like this:

$('input').change(function () {
    $('form').submit();
});

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

This is a good plugin to upload files using ajax

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

You know instead of fetching the same item multiple times, why not just reuse it:

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

What kind of error are you having? can you post it?

UPDATE

Since you cannot set the attribute yourself here is a work around:

Put the form in an iframe, and attach an onchange event to the input button. when the user select a file, you trigger the necessary code to upload the file (submit), then the parent window can close the iframe.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM