1. 程式人生 > >Django中的文件上傳+Ajax詳細應用

Django中的文件上傳+Ajax詳細應用

submit pull 什麽 而是 字符串 dcl lur func .sh

【001】基於Ajax上傳文件

原則:如果我們使用Ajax操作在涉及到文件上傳時,那就要使用FormData

1.首先要明白:上傳文件使用input輸入框的類型是file: 技術分享圖片 技術分享圖片 2.後臺我需要拿到前端傳遞過來的文件對象,註意文件對象並不在request.post裏面,而是在request.files裏面:
# 獲取文件對象file_obj,如果想獲取文件的名字,使用file_obj.name即可
file_obj = request.FILES.get("cFile")

3.contentType:筆者在上一節中說過即客戶端告訴服務端決定以什麽樣的數據編碼格式發送給服務端,在請求頭中,如果沒有特意指定該參數,那麽默認就是以urlencoded的形式為我們組裝數據。

註意contentType是前端頁面在請求向服務端發送數據,具體以什麽格式組裝數據然後發送過去,就取決於contentType的類型,默認是如下的類型,就是以鍵值對鍵值對的形式組裝發送過去: 技術分享圖片

4.根據上面所說,現在我要傳輸一個文件過去,因為鍵值對中涉及到一個文件,如果還是按照默認的編碼方式發送過去,我們在服務端打印request.body,拿到的只能是一個文件名:

技術分享圖片

這顯然不滿足我們的要求,因為我們是需要文件對象的。所以不能采用默認的形式發送數據,因為涉及到二進制數據,怎麽設置?昨天使用Ajax直接指定參數即可,現在我使用Form表單來傳遞包括二進制文件在內的數據,所以需要添加一個參數:enctype,這裏我們選中multipart/form-data,如下:

技術分享圖片

我以後上傳圖片,音樂等二進制文件時,都可以結合form-data進行使用,當我們修改格式後,就可以看看請求頭中的Content-Type:

技術分享圖片

然後再來看看服務端的打印結果:

技術分享圖片

技術分享圖片

request.FILES接收的是文件對象,InMemoryUploadFile是我們拿到的文件句柄,這樣就上傳頭像了!

通過上面的例子可知,form-data既可以支持表單數據,例如我們打印request.POST打印出表單數據,又支持二進制數據,例如圖片,音頻等文件。但是urlencoded只支持表單數據。這是兩者的根本區別,一定要區分開。

request.FILES是一個字典,現在我們得到一個文件對象:

技術分享圖片

通過文件句柄的name屬性打印出圖片的名字:

技術分享圖片

記住使用Ajax上傳文件時候,input輸入框的類型要修改為button,不要使用submit.

技術分享圖片

技術分享圖片

$(""button")表示選擇 type="button" 的 <button> 元素和 <input> 元素。

通過Jquery獲取二進制文件對象:

使用Ajax上傳一個二進制文件時候,如何組裝鍵值對的時候註意取出值: 1.首先通過Jquery拿到文件所屬的input標簽: $("#cFile") 2.將Jquery對象轉換為Dom對象: $("#cFile")[0] 此時我們就拿到了dom對象 3.調用dom對象的files方法,拿到一個文件list:Filelist,接下來只需要獲取 該文件列表的第一個元素即可:$("#cFile")[0].files[0]即可獲取到文件對象 技術分享圖片

4.那我們能不能按照如下的方式寫呢?

技術分享圖片

按照上述的方式這樣寫直接報錯:

技術分享圖片

那是因為你傳二進制數據,按照表單數據發送肯定是不行的;所以肯定不能按照上面的方式,那麽Ajax利用的也是FormData,要想使用Ajax上傳二進制文件就需要使用到FormData,我們也不需要什麽form表單了,變為如下:

技術分享圖片

使用如下的形式發送數據:

技術分享圖片

直接將formData傳遞過去即可。點擊發送依然有問題,那是因為Content-Type默認是urlencoded,現在我使用Ajax發送,那就要修改兩個參數,都設置為False

技術分享圖片

前面我們說過,無論你的Data裏面寫什麽數據,ajax發送的時候都會以contentType規定的格式對你的數據進行編碼傳送;你默認是urlencoded,那我就以
urlencoded的格式發送過去;如果你修改為Json,那我就以json的格式發送。

但是不是所有的情況都需要進行編碼傳送,例如我傳遞一個二進制文件,二進制沒有必要進行編碼,按照原來的文件格式發送即可。

Ajax發送數據的時候,首先會查看processData的值,如果為True,表明我需要對該數據進行處理後發送,至於做什麽樣的處理,就得問contentType了,contentType會告訴Ajax是把數據處理成urlencoded的形式,還是json字符串

也就是說兩者配合工作,如果設置processData為False,表示我的數據是什麽樣子,你就將數據發送到服務器,讓服務器自己接受。因此processData的值就只有兩個,True:表示我對數據進行預處理,至於怎麽處理,就是contentType要幹的事,為False,那就告訴ajax不做處理,直接發送二進制數據即可。
因此processData設置為False,那麽contentType也沒用了,直接設置為False,將默認的urlencoded清空掉,如果你不設置,那麽它默認又以urlencoded進行發送。
現在你不使用表單形式(urlencoded)的形式進行發送了,那麽我傳送csrf_token的時候也是二進制,那肯定也過不了,所以我們得在請求頭重添加一個X-CSRFToken: 技術分享圖片

這裏是在網頁中的input輸入框中取值,所以使用csrfmiddlewaretoken,如果從cookie中取值,那就得使用csrftoken,這裏要註意區分。

綜上所述,上傳文件有兩種形式:

總結:上傳文件有兩種方式: 【01】.form表單數據進行提交: 兩處修改:1.在form標簽後面增加一個屬性enctype="multipart/form-data" 2.由於上傳的文件是二進制數據,所以還需要修改contentType,讓它變為formdata:

技術分享圖片

【02】使用Ajax提交:

1.實例化表單數據對象:

技術分享圖片

這裏面的數據是表單數據還是非表單數據都可以

2.然後按照FormData實例化的結果發送過去即可:

技術分享圖片

最後分享一個實際的例子供各位參考:

$(document).ready(function () {
    // 為每個input輸入框綁定的blur事件,並將值通過Ajax發送給後臺進行校驗
    $("#id_username").blur(function () {
        $.ajax({
            url:"/validate_username/",
            type:"get",
            data:{"username": $("#id_username").val()},
            success:function (data) {
                if(data.flag){
                    alert("This username has benn registered");
                    // $("#error").html("用戶名已被註冊");
                }else{
                    console.log(data.flag);
                }
            }
        });
        $("#register_btn").submit();
    });

      var handlerPopup = function (captchaObj) {

        // 成功的回調
        captchaObj.onSuccess(function () {
            function foo() {
            $(".error").html("");
        }
            var validate = captchaObj.getValidate();
            var $formData = new FormData();
            $formData.append("username",$(#id_username).val());
            $formData.append("password", $("#id_password").val());
            $formData.append("password_again", $("#id_password_again").val());
            $formData.append("email", $("#id_email").val());
            $formData.append("mobile", $("#id_mobile").val());
            $formData.append("avatar_image", $("#avatar_file")[0].files[0]);
            $formData.append("csrfmiddlewaretoken", $("input[name=‘csrfmiddlewaretoken‘]").val());
            $formData.append("geetest_challenge", validate.geetest_challenge);
            $formData.append("geetest_validate", validate.geetest_validate);
            $formData.append("geetest_seccode", validate.geetest_seccode);

            $.ajax({
                url: "/pc-geetest/ajax_register_validate", // 進行二次驗證
                type: "post",
                dataType: "json",
                data: $formData,
                processData: false,
                contentType:false,
                success: function (data) {
                    if (data && (data.status === "success")) {
                        // 註冊數據滿足規則,提示註冊成功的信息,3秒後跳轉到登入界面
                        $("#register_success").html("Congratulations For Register");
                        setTimeout(foo, 3000);
                    } else {
                        //註冊數據不滿足規則,那就提示錯誤信息, error_msg是一個字典
                         // 當第一次提示有3個字段錯誤的時候,我修改一個錯誤後,那麽還剩下2個,剛才剩下的那個
                        //錯誤應該消失,因為這又是一個ajax請求。
                        $("span").html("");
                        $(".form-group div").each(function () {
                        //其次應該將input輸入框的錯誤紅色提示消掉,根據後面的可知,我們應該將input輸入框的父級標簽div
                            $(this).removeClass("has-error");
                        });

                        $.each(data.error_msg, function (key, value) {
                            console.log(data.error_msg);
                            //1.新建span標簽,並增加相應的樣式
                            $span = $("<span>");
                            $span.addClass("pull-right").css("color", "red").html(value[0]);
                            //2.將span標簽放在對應input輸入框下面,通過$("#id_"+key)實現
                            // .parent()是獲取input標簽的父級標簽,要想讓整個input輸入框變紅,必須為div
                            $("#id_"+key).after($span).parent().addClass("has-error");
                            // 3.判斷全局鉤子函數中定義的密碼是否錯誤
                            if(key === "__all__"){
                                $("#id_password_again").after($span).parent().addClass("has-error");
                            }
                        })
                    }
                }
            });
        });
        $("#popup-submit").click(function () {
            captchaObj.show();
        });
        // 將驗證碼加到id為captcha的元素裏
        captchaObj.appendTo("#popup-captcha");
    };

     // 驗證開始需要向網站主後臺獲取id,challenge,success(是否啟用failback)
    $.ajax({
        url: "/pc-geetest/register?t=" + (new Date()).getTime(), // 加隨機數防止緩存
        type: "get",
        dataType: "json",
        success: function (data) {
            initGeetest({
                gt: data.gt,
                challenge: data.challenge,
                product: "popup",
                offline: !data.success
            }, handlerPopup);
        }
    });
});

Django文件上傳:https://www.cnblogs.com/linjiqin/p/3731751.html

https://www.cnblogs.com/zhaopengcheng/p/5633154.html

http://blog.csdn.net/a18852867035/article/details/66976028

https://www.cnblogs.com/nulige/p/6582355.html

Django中的文件上傳+Ajax詳細應用