AjaxFileUpload方法と原理分析

16078 ワード

A jax FileUpload需要
従来のフォーム形式でファイルをアップロードします.  必ずページ全体を更新します. インタフェースを更新しないでファイルのアップロードを実現しますか?
HTML 4の下で、賢いプログラマー達が発明しました. ajax file アップロード 方式(form+ hidden iframe方式) 本稿に紹介する対象.
 HTML 5でXMLHttpRequestが非同期アップロードファイルを実現しました.http://wenzhixin.net.cn/2013/11/28/ajax_file_upload_html5を選択します
 
オープンソースプロジェクト
公式サイトはhttps://github.com/davgothic/AjaxFileUpload
このプラグインはサポートされています ファイルを選択したら、  すぐにファイルをアップロードします. 全体ページは更新されません.  また、バックグラウンドから戻ってきたjsonによってユーザーにアップロードされた状況を報告することができます.
 
使用説明
このプラグインはjqueryライブラリに基づいています.  jqueryライブラリを参照する必要があります.
    <script type="text/javascript" src="jquery-1.6.1.min.js"></script>
    <script type="text/javascript" src="../jquery.ajaxfileupload.js"></script>
 
ファイルコントロール(このプラグインを使っても、フォームは不要です.  書き込み):
    <form method="post" action="" enctype="multipart/form-data">
        <label>File Input: <input type="file" name="file" id="demo1" /></label>
        <div id="uploads">

        </div>
    </form>
このプラグインを使ってコントロールを初期化します.
    <script type="text/javascript">
        $(document).ready(function() {
            $("#demo1").AjaxFileUpload({
                onComplete: function(filename, response) {
                    $("#uploads").append(
                        $("<img />").attr("src", filename).attr("width", 200)
                    );
                }
            });
        });
    </script>
 
バックグラウンドはPHP参照を実現します.
<?php
/**
 * This is just an example of how a file could be processed from the
 * upload script. It should be tailored to your own requirements.
 */
// Only accept files with these extensions
$whitelist = array('jpg', 'jpeg', 'png', 'gif');
$name      = null;
$error     = 'No file uploaded.';
if (isset($_FILES)) {
    if (isset($_FILES['file'])) {
        $tmp_name = $_FILES['file']['tmp_name'];
        $name     = basename($_FILES['file']['name']);
        $error    = $_FILES['file']['error'];
        
        if ($error === UPLOAD_ERR_OK) {
            $extension = pathinfo($name, PATHINFO_EXTENSION);
            if (!in_array($extension, $whitelist)) {
                $error = 'Invalid file type uploaded.';
            } else {
                move_uploaded_file($tmp_name, $name);
            }
        }
    }
}
echo json_encode(array(
    'name'  => $name,
    'error' => $error,
));
die();
 
カスタムインターフェース
4つのカスタムインターフェース、 カスタマイズ可能な内容は以下の通りです.
1 アップロードurl(カスタムカスタム action
2  submitイベントを送信しました.たとえばファイルの拡張子検証が成功しませんでした. アップロードしません
3  ファイルchangeイベントを選択しました. プログレスバーなどを待つ)
4 送信完了後の応答イベント complettee(提出成功後、 提出結果をリストに追加します.
    <form method="post" action="" enctype="multipart/form-data">
        <label>File Input: <input type="file" name="file" id="demo1" /></label>
    </form>
    <script type="text/javascript" src="jquery-1.6.1.min.js"></script>
    <script type="text/javascript" src="../jquery.ajaxfileupload.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            var interval;
            function applyAjaxFileUpload(element) {
                $(element).AjaxFileUpload({
                    action: "upload.php",
                    onChange: function(filename) {
                        // Create a span element to notify the user of an upload in progress
                        var $span = $("<span />")
                            .attr("class", $(this).attr("id"))
                            .text("Uploading")
                            .insertAfter($(this));
                        $(this).remove();
                        interval = window.setInterval(function() {
                            var text = $span.text();
                            if (text.length < 13) {
                                $span.text(text + ".");
                            } else {
                                $span.text("Uploading");
                            }
                        }, 200);
                    },
                    onSubmit: function(filename) {
                        // Return false here to cancel the upload
                        /*var $fileInput = $("<input />")
                            .attr({
                                type: "file",
                                name: $(this).attr("name"),
                                id: $(this).attr("id")
                            });
                        $("span." + $(this).attr("id")).replaceWith($fileInput);
                        applyAjaxFileUpload($fileInput);
                        return false;*/
                        // Return key-value pair to be sent along with the file
                        return true;
                    },
                    onComplete: function(filename, response) {
                        window.clearInterval(interval);
                        var $span = $("span." + $(this).attr("id")).text(filename + " "),
                            $fileInput = $("<input />")
                                .attr({
                                    type: "file",
                                    name: $(this).attr("name"),
                                    id: $(this).attr("id")
                                });
                        if (typeof(response.error) === "string") {
                            $span.replaceWith($fileInput);
                            applyAjaxFileUpload($fileInput);
                            alert(response.error);
                            return;
                        }
                        $("<a />")
                            .attr("href", "#")
                            .text("x")
                            .bind("click", function(e) {
                                $span.replaceWith($fileInput);
                                applyAjaxFileUpload($fileInput);
                            })
                            .appendTo($span);
                    }
                });
            }
            applyAjaxFileUpload("#demo1");
        });
    </script>
 
原理を実現する
次の文章の説明を参照してください.
http://wenzhixin.net.cn/2013/11/27/ajax_file_upload_iframe
 
ここでは、このオープンソース項目のコードを紹介します.
1、 Ajax FileUploadを適用する はい、 fileコントロールの後、 このfileコントロールは結合されます. changeイベント、 イベント関数はオンチャンです.
        return this.each(function() {
            var $this = $(this);
            if ($this.is("input") && $this.attr("type") === "file") {
                $this.bind("change", onChange);
            }
        });
2、 ユーザがファイルを選択したら、 トリガー changeイベント、 オンチャンを呼び出します 関数
     この関数は、 まずクローンを作成します fileコントロール、 あわせて このクローンコントロールは、  AjaxFileUploadも使用します.  初期化(バインディングされました. オンChange関数、ステータスは元のコントロールと同じです.
     を選択して、このコントロールを 挿入 元のコントロールの前に
                $clone   = $element.removeAttr('id').clone().attr('id', id).AjaxFileUpload(options),
。。。。。
            // We append a clone since the original input will be destroyed
            $clone.insertBefore($element);
     後に作成  隠していた iframe, を選択して初期化します iframeの ロードイベント(form提出後応答のフレームワーク)、 イベント関数は 応答処理関数:
                iframe   = createIframe(),
。。。。

            iframe.bind("load", {element: $clone, form: form, filename: filename}, onComplete);
     後に提出されたフォームを作成します. formの提出イベントをonSubmitにバインドして提出する動作をします.
                form     = createForm(iframe);
。。。。。
            form.append($element).bind("submit", {element: $clone, iframe: iframe, filename: filename}, onSubmit).submit();
 
3、2ステップでformを提出した後、ファイルのアップロードに成功し、iframeのロードイベントがトリガされ、onComplettee関数を実行し、結果を処理します. 処理が終わったら オンチャンで作成した フォームm 和 iframe削除:
        function onComplete (e) {
            var $iframe  = $(e.target),
                doc      = ($iframe[0].contentWindow || $iframe[0].contentDocument).document,
                response = doc.body.innerHTML;

            if (response) {
                response = $.parseJSON(response);
            } else {
                response = {};
            }
            //         
            settings.onComplete.call(e.data.element, e.data.filename, response);
            
            // Remove the temporary form and iframe
 e.data.form.remove(); $iframe.remove();
        }
 
 
changeイベントは一回だけ有効です.
正しいなら file コントロールの適用 ajaxfileupload コントロール初期化後、 次に設定します 追加のchange イベント、 最初のユーザがファイルを選択してアップロードした後、 なくします からです ファイルコントロールをclone体に置き換えます. ただし、clone体にはoldイベントはありません. 有効コードは cloneパラメータは空です 浅いコピーを意味します.
        function onChange(e) {
            var $element = $(e.target),
                id       = $element.attr('id'),
                $clone   = $element.removeAttr('id').clone().attr('id', id).AjaxFileUpload(options),
                filename = $element.val().replace(/.*(\/|\\)/, ""),
                iframe   = createIframe(),
                form     = createForm(iframe);

            // We append a clone since the original input will be destroyed
            $clone.insertBefore($element);
 
解決方法は、プロキシを使用します.
$(document).on('change', '#upload', function() { });
参考:
http://wenzhixin.net.cn/2013/11/26/jquery_file_upload_change_オンス