day23-基于ajax文件上传和上传图片之后预览

一、前言

 之前我们是用forms的方式去上传文件,后台去读取,然后去写入到后台去,具体博客:day18-Django获取1个或多个数据以及文件上传 ,我们今天使用的是,ajax方式去操作文件上传的动作,这边有三种方式,

  1. 原生ajax上传文件
  2. jquery的ajax的上传文件
  3. iframe方式(伪ajax方式)上传文件

 这个上传文件我们说完了,下面还有就是上传图片之后的预览,这个我们也要学会的,这个我们下面会一步一步的详细的介绍的,下面进入正题吧。

二、操作前提

2.1、路由url的设置

说明:我们首先设置一下路由

from django.urls import path
from app01.views import test

urlpatterns = [
    path('upload/',test.upload),   #上传文件页面
    path('upload_file/',test.upload_file),  #上传文件功能
]

2.2、upload函数

说明:通过upload函数显示上传页面

def upload(request):
    return render(request,'upload.html')

2.3、upload_file函数

说明:这边主要处理上传过来的文件,写到服务器上

def upload_file(request):
    username = request.POST.get('username')
    fafafa = request.FILES.get('fafafa')
    print(username,fafafa)  #输出 root settings.xml
    with open(fafafa.name,'wb') as f:
        for item in fafafa.chunks():  #把文件写入到服务器端
            f.write(item)
    ret = {'code':True,'data':request.POST.get('username')}
    import json
    return HttpResponse(json.dumps(ret))

2.4、upload.html的模板

说明:这边我只写html和css部分,js上传功能,我们下面详细的讲解,这边静态的东西如下:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .upload{
            display: inline-block;
            padding: 10px;
            background-color: brown;
            top: 0;
            bottom: 0;
            right: 0;
            left: 0;
            z-index: 99;
        }
        .file{
            width: 100px;height: 50px;opacity: 0;
            position: absolute;
            top: 0;
            bottom: 0;
            right: 0;
            left: 0;
            z-index: 100;
        }
    </style>
</head>
<body>
    <!--原生ajax和jquery ajax上传文件定义的html-->
    <div style="position: relative;width: 100px;height: 50px;">
        <!--因为这个改不了,所以这个上传的标签只能自定义组件,就是在外面嵌套div-->
        <input class="file" type="file" id="fafafa" name="afafaf">
        <a class="upload">上传</a>
    </div>
    <!--原生ajax的触发按钮-->
    <input type="button" value="提交XHR" onclick="xhrSubmit();"/>
    <!--jquery的发送方式触发按钮-->
    <input type="button" value="提交Jquery" onclick="jqSubmit();"/>
    <!--分隔符-->
    <hr/>
    <!--伪类ajax上传文件定义的html-->
    <form action="/upload_file/" method="post" enctype="multipart/form-data" target="ifm1">
        <iframe id="ifm1" name="ifm1"></iframe> <!--正常情况下,iframe在前端是不显示的,但是我们这边为了方便调试,所以暂时打开-->
        <input type="file" name="fafafa"/>
        <!--iframe方式上传文件-->
        <input type="submit" onclick="iframeSubmit();" value="Form提交"/>
    </form>
    <!--图片存放的地方-->
    <div id="preview"></div>
</body>
</html>
upload.html

如图:

三、文件上传

3.1、原生ajax文件上传

说明:原生ajax需要在FormData的支持下,才能发送文件的对象到后台

<script src="/static/jquery-1.12.4.js"></script>
<script>
    function xhrSubmit(){
        //$('#fafafa')[0] //[0]表示是dom对象
        var file_obj = document.getElementById("fafafa").files[0]; //files表示你要上传的文件,这边只上传一个文件,所以用[0],指的就是上传的文件对象
        var fd = new FormData(); // formdata相当于form表单
        fd.append('username','root'); // 加普通字符串四可以的,加obj对象也是可以的
        fd.append('fafafa',file_obj);
        var xhr = new XMLHttpRequest();
        xhr.open('post','/upload_file/',true);
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                //接收完毕
                var obj = JSON.parse(xhr.responseText);
                console.log(obj);
            }
        };
        xhr.send(fd); //这边发送的话,就直接发送fd对象了
    }
</script>

3.2、jquery的方式发送

说明:利用jquery自带的ajax的功能发送文件、图片或者等其他静态文件,这种方式也是要依赖 formdata的

<script>
    function jqSubmit(){
        var file_obj = document.getElementById('fafafa').files[0];
        var fd = new FormData();
        //发普通文本的话,我们是这样发的,但是如果发文件或者图片的话,你要告诉jquery,因为jquery内部需要处理
        fd.append('username','root');
        fd.append('fafafa',file_obj);

        $.ajax({
            url:'/upload_file/',
            type:'post',
            data:fd, //直接发送formdata对象给后端
            processData:false,//tell jQuery not to process the data
            contentType:false,// tell jQuery not to set contentType
            success:function(args,statusText,xhr){
                console.log(args);
                console.log(statusText);
                console.log(xhr); //XMLHttprequest对象
            }
        })
    }
</script>
</body>

前端返回的信息如图,这个我们都可以通过xmlhttprequest对象可以获取到:

 

3.3、iframe的方式上传(伪ajax上传)

说明:我们现在用第三种方式上传,其实大部分都是以这种方式上传,包括抽屉网,这个我就不给大家介绍了,可以去看看。

<script src="/static/jquery-1.12.4.js"></script>
<script>
    function iframeSubmit(){  //form本身就已经提交了
        $('#ifm1').bind('load',function(){  //提交之后,会自动执行iframe会自动执行onload事件
            var text = $('#ifm1').contents().find('body').text(); //获取iframe body中的内容
            var text_obj = JSON.parse(text);
            console.log(text_obj);
        })
    }
</script>

四、上传图片之后预览

4.1、upload_file函数修改

说明:我们这边在 后台的 static 下建一个imgs 文件夹,我们所有的图片都放在这个下面,所以我们返回一个图片路径给前端,代码如下:

def upload_file(request):
    username = request.POST.get('username')
    fafafa = request.FILES.get('fafafa')
    import os
    img_path = os.path.join('static/imgs/',fafafa.name)  #设置img的路径
    with open(img_path,'wb') as f:  #直接写入指定 static/imgs文件下
        for item in fafafa.chunks():
            f.write(item)
    ret = {'code':True,'data':img_path} #data这边返回是图片的路径
    import json
    return HttpResponse(json.dumps(ret))

4.2、上传预览

说明:上传图片之后,我们预览图片,js代码如下:

<script src="/static/jquery-1.12.4.js"></script>
<script>
    function iframeSubmit(){
        $('#ifm1').bind('load',function(){
            var text = $('#ifm1').contents().find('body').text();
            var text_obj = JSON.parse(text);
            //存在就清空一下
            $('#preview').empty();
            var img_tag = document.createElement('img');
            img_tag.src = '/' + text_obj.data;  //这边由于后台的path是static/imgs,所以这边要在前面加一个 '/'
            $('#preview').append(img_tag);  //在div中加一个img标签
        })
    }
</script>

显示效果图:

4.3、自动上传预览

说明:就是说我们不需要点击From提交按钮,预览图片,我只要上传图片了,就自动给我展示,这边要给上传的 按钮帮你一个  onchange事件,就是说,只要上传的图片已经改变,就自动提交

1、前端 iframe 的代码改进

<form id="fm1" action="/upload_file/" method="post" enctype="multipart/form-data" target="ifm1">
    <!--iframe默认情况下不显示,不让用户看到,但是我们调试的时候可以打开-->
    <iframe id="ifm1" name="ifm1" style="display: none"></iframe>
    <!--绑定onchange事件,只要一改变,让整个表单提交-->
    <input type="file" name="fafafa" onchange="changeUpload();"/>
    <!--iframe方式上传文件-->
    <!--<input type="submit" onclick="iframeSubmit();" value="Form提交"/>-->
</form>
<!--图片存放的地方-->
<div id="preview"></div>

2、js的代码

说明:我们先绑定一个事件,首先先要执行的iframe的onload的事件,然后再直接提交 form表单就可以了。

<script src="/static/jquery-1.12.4.js"></script>
<script>
    function changeUpload(){
        // 先绑定一个事件,然后我们再提交,上面的submit按钮直接注释掉
        $('#ifm1').bind('load',function(){
            var text = $('#ifm1').contents().find('body').text();
            var text_obj = JSON.parse(text);
            //存在就清空一下
            $('#preview').empty();
            var img_tag = document.createElement('img');
            img_tag.src = '/' + text_obj.data;
            $('#preview').append(img_tag);
        });
        $('#fm1').submit(); //这步操作放在 $('#ifm1').bind('load',function(){}上面也是可以的,可能这个是一个自执行函数,肯定是要先提交,然后才会获取图片
    }
</script>

效果图:

五、总结

  1、原生ajax(xhr)和jquery ajax($.ajax) 都需要依赖  FormData 对象,但是这个东西不是所有的浏览器都支持的,IE的低版本不支持。

  2、iframe这个东西在所有浏览器上都使用,其他两种方式只有非IE浏览器使用。

  3、三个的优先级顺序: iframe  ->  jquery ajax -> 原生 ajax

posted @ 2018-05-16 15:32  帅丶高高  阅读(171)  评论(0编辑  收藏  举报