前端之web上傳文件的方式


前端之web上傳文件的方式

本節內容

  1. web上傳文件方式介紹
  2. form上傳文件
  3. 原生js實現ajax上傳文件
  4. jquery實現ajax上傳文件
  5. form+iframe構造請求上傳文件

1. web上傳文件方式介紹

在web瀏覽器上傳文件一般有以下幾種方式:

  • form表單上傳文件
  • 原生js實現ajax上傳文件
  • jquery實現ajax上傳文件
  • form+iframe上傳文件

其中form提交數據之后會整個刷新頁面;
js通過ajax上傳文件雖然不會刷新整個頁面,但是他們都是通過使用formdata對象實現的,formdata對象在老版本的瀏覽器中並不支持;
為了兼容老版本瀏覽器,使用iframe方式提交;

下面幾節就分別就這幾種方式實現上傳文件來舉例說明。

2. form上傳文件

這是最原始的一種方式,最開始學習web的時候就是使用這種方式提交。
注意:在form表單中如果要上傳文件,一定要設置這個參數: enctype=”multipart/form-data”表示封裝數據類型,把數據分成一個一個小段傳輸。

html代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .show-img{
            display: inline-block;
            width: 200px;
            height:200px;
        }
    </style>
</head>
<body>
    <h1>form表單上傳文件</h1><hr>
    <form action="/test/" method="POST" enctype="multipart/form-data">
        <p>名稱:<input type="text" name="user"></p>
        <p>文件:<input type="file" name="testfile"></p>
        <p><input type="submit" value="提交"></p>
    </form>
    {% for i in imglist %}
        <img class="show-img" src="/{{ i.0 }}">
    {% endfor %}
</body>
</html>

在后端要注意上傳過來的文件是通過req.FILES.get() 方法接收的。
后端代碼:

def test(req):
    if req.method=="GET":
        imglist=models.Img.objects.all().values_list("img_path")
        return render(req,"test.html",{"imglist":imglist})
    elif req.method=="POST":
        user=req.POST.get("user")
        file=req.FILES.get("testfile")
        path=os.path.join("static","imgs",file.name)
        with open(path,"wb") as f:
            for chunk in file.chunks():
                f.write(chunk)
        print(user,file.name,file.size)
        models.Img.objects.create(img_path=path)
        return redirect("/test/")

3. 原生js實現ajax上傳文件

js源碼:

document.getElementById("js_post").onclick=function(){
    var xml=new XMLHttpRequest();
    var data=new FormData; //創建formdata對象
    data.append("testfile",document.getElementById("file_upload").files[0]);//找到對象之后的file[0]對應的就是文件對象
    xml.open("POST","/test/",true);
    xml.onreadystatechange=function(){
        if(xml.readyState==4 && xml.status==200){  //判斷狀態到4了並且返回狀態碼是200時才做操作
            var rsp_data=JSON.parse(xml.responseText);  //反序列化
            if (rsp_data.state){
                var url="/"+rsp_data.data;  //拼接路徑
                var obj=document.createElement("img");  //創建標簽
                obj.className="show-img";  //給標簽加樣式
                obj.src=url;  //給標簽加url
                document.getElementById("imgs").appendChild(obj);
            }
        }
    };
    xml.send(data)
}
`

html源碼:

<hr><h1>ajax上傳文件</h1><hr>
<p>文件:<input id="file_upload" type="file" name="testfile"></p>
<p><button id="js_post">原生js提交</button>  <button id="jquery_post">jquery提交</button></p>
<div id="imgs">
    {% for i in imglist %}
        <img class="show-img" src="/{{ i.0 }}">
    {% endfor %}
</div>

后端源碼:

def test(req):
    if req.method=="GET":
        imglist=models.Img.objects.all().values_list("img_path")
        return render(req,"test.html",{"imglist":imglist})
    elif req.method=="POST":
        user=req.POST.get("user",None)
        file=req.FILES.get("testfile")
        path=os.path.join("static","imgs",file.name)
        with open(path,"wb") as f:
            for chunk in file.chunks():
                f.write(chunk)
        print(user,file.name,file.size)
        models.Img.objects.create(img_path=path)
        # return redirect("/test/")
        msg={"code":200,"state":True,"data":path}
        return HttpResponse(json.dumps(msg))

注意:FormData對象在添加文件對象的時候並不是把標簽直接給append進去,而是找到標簽之后.file(0)才是文件對象

4. jquery實現ajax上傳文件

這里的html代碼和后端代碼相對上面沒有改變,這里就不列出來了。
jquery代碼:

$("#jquery_post").on("click",function(){
            var data=new FormData;
            data.append("testfile",document.getElementById("file_upload").files[0]);
            $.ajax({
                url:"/test/",
                type:"POST",
                dataType:"JSON",
                data:data,
                contentType: false,
                processData: false,
                success:function(rst){
                    if(rst.state){
                        var url="/"+rst.data;
                        $('<img class="show-img" src="'+url+'">').appendTo("#imgs")
                    }
                }
            })
        })

注意:jquery的ajax會自動把我們的數據轉換成字符串,不想轉換時需要在ajax里面寫入:contentType: false,processData: false,

5. form+iframe構造請求上傳文件

html代碼:

<hr><h1>form+iframe上傳文件</h1><hr>
    <p><iframe id="uploadfile" name="uploadfile" style="display: none"></iframe></p>  <!--注意這里的name要和form中的target一致-->
    <form target="uploadfile" action="/test/" method="POST" enctype="multipart/form-data">
        <p>名稱:<input type="text" name="user"></p>
        <p>文件:<input type="file" name="testfile"></p>
        <p><input type="submit" value="提交"></p>
    </form>
    <div id="imgs">
        {% for i in imglist %}
            <img class="show-img" src="/{{ i.0 }}">
        {% endfor %}
    </div>

注意:這里的iframe的name的值一定要和form的target的值一樣,這樣才能實現綁定

js代碼:

$("#uploadfile").on("load",function(){  //iframe里面有個方法是onload,當上傳數據成功之后服務器返回數據時才會觸發該事件
            var rst=JSON.parse(this.contentDocument.body.textContent);//拿到iframe里面的內容需要通過contentDocument才能拿到里面的dom對象
            if (rst.state){
                var url="/"+rst.data;
                        $('<img class="show-img" src="'+url+'">').appendTo("#imgs")
            }
        })

注意:拿到iframe里面的內容需要通過contentDocument才能拿到里面的dom對象
經過實際檢測,當鼠標點擊提交速度比較快時,js通過ajax提交數據沒有問題,但是iframe就無法提交所有數據。。。
原因是ajax是異步加載的,而iframe更像是通過瀏覽器打開了一個新標簽,等待服務端傳輸回來的數據。所以,當提交速度過快時無法達到相應的效果。
使用iframe的唯一一個好處目前來看也就是兼容老版本的瀏覽器罷了。。。
隨着時間的流逝,這種方式終將被淘汰。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM