柴少的博客 也许终将一事无成,却不能甘于平庸。

Django文件上传与获取多个值(三)

一、一个简单的文件上传的方式

官网:https://docs.djangoproject.com/en/2.0/topics/http/file-uploads/

urls.py加一条路由视图:

url(r'upload',views.upload),

主站views.py上加upload函数:

from django.shortcuts import  HttpResponse
from django.shortcuts import render
import datetime
from django.shortcuts import redirect
from django.core.files.uploadedfile import InMemoryUploadedFile
import  os
def upload(request):
    if request.method == "GET":
        return render(request, 'upload.html')
    else:
        ff = request.POST.get('fafile')
        obj = request.FILES.get('fafile')  #获取文件
        print(ff, obj, type(obj), obj.name)  ##ff应该会输出None,obj是文件,看类型就不单单是文件名,obj.name为文件名
        file_path = os.path.join('upload', obj.name)  ##在指定文件前面加上上传目录位置
        f = open(file_path, mode="wb")
        #f = open(obj.name, mode="wb")   #打开一个文件进行文件接收,但是这样不能指定文件位置
        for i in obj.chunks():    #chunks是把文件分块,数据本来就是一块块的进行传输的
            f.write(i)
        f.close()
        return render(request, 'upload.html')

#InMemoryUploadedFile  #这个是加载用户上传文件模块

再有一个upload.html:

<body>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <p>
            <input type="file" name="fafile">
        </p>
        <p><input type="submit" value="提交"></p>
    </form>
</body>

#enctype="multipart/form-data"加上这句话就是文件以文件形式传输到后台,不然只是把文件名称传过去

#然后再创建一个upload目录用于存放upload的内容。

下面是测试内容:

图片.png

图片.png

#从上图可以看到 ff = request.POST.get('fafile') #这个只能获取字符串,但是当前端html页面以文件形式传输时这里就获取不到值了。

#上图是django后台抓到的打印信息。

图片.png

#可以看到已经将上传的内容存放到了指定的目录下面。客户端发来请求发到服务端,有请求头,请求尾,服务端会根据请求头里的信息做提取,django会把表单这些内容提取到POST中,把文件提取到FILE中。

request.FILES中的值均为UploadedFile类文件对象。

UploadedFile是类文件对象,具有以下方法和属性:

UploadedFile.read()   #读取整个上传文件的数据,文件较大时慎用,可能会耗尽内存。
UploadedFile.multiple_chunks(chunk_size=None)  #如上传文件足够大,要分成多个部分读入时,返回True.默认情况,当上传文件大于2.5M时,返回True。但这一个值可以配置。
UploadedFile.chunks(chunk_size=None)  #返回一个上传文件的分块生成器。如multiple_chunks()返回True,必须在循环中使用chrunks()来代替read()。一般情况下直接使用chunks()就行。
UploadedFile.name  #上传文件的name。
UploadedFile.size  #上传文件的大小(字节)。
UploadedFile.content_type  #上传文件时的content_type报头,例如(e.g. text/plain or application/pdf). 
UpladedFile.charset  #编码

二、getlist获取多个值

urls.py加一条路由视图:

url(r'zhuce',views.zhuce),

主站views.py上加zhuce函数:

def zhuce(request):
    if request.method == "GET":
        return render(request,'zhuce.html')
    elif request.method == "POST":
        v = request.POST.get('gender')
        f = request.POST.getlist('favor')
        c = request.POST.get('city')
        c2 = request.POST.getlist('city2')
        print(v, f, c, c2)
        return render(request, 'zhuce.html')

zhuce.html的配置:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
    <link rel="stylesheet" href="/static/commons.css" />
<body>
<form action="/zhuce" method="post">
        <p>
            <input type="text" name="user" placeholder="用户名" />
        </p>
        <p>
            <input type="password" name="pwd" placeholder="密码" />
        </p>
        <p>
            男:<input type="radio" name="gender" value="1" />
            女:<input type="radio" name="gender" value="2"/>
            人妖: <input type="radio" name="gender" value="3" />
        </p>
        <p>
            篮球:<input type="checkbox" name="favor" value="1">
            足球:<input type="checkbox" name="favor" value="2">
            排球:<input type="checkbox" name="favor" value="3">
        </p>
        <p>
            <select name="city">
                <option value="sh">上海</option>
                <option value="bj">北京</option>
                <option value="tj">天津</option>
            </select>
        </p>
         <p>
            <select name="city2" multiple> 
                <option value="sh">上海</option>
                <option value="bj">北京</option>
                <option value="tj">天津</option>
            </select>
        </p>
        <p><input type="submit" value="提交"></p>
    </form>
    <script src="/static/jquery.min.js"></script>
</body>
</html>

图片.png

图片.png

#从django后台打印的post信息可以看到多选框里面的内容是列表的形式。

三、Ajax文件上传

3.1 ajax原生实现上传

urls.py:

url(r'^upload/$',views.upload),
url(r'^upload_file/$',views.upload_file),

upload.html :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .upload{
            display: inline-block;padding: 10px;
            background-color: brown;
            position: absolute;
            top: 0;
            bottom: 0;
            right: 0;
            left: 0;
            z-index: 90;
        }
        .file{
            width: 100px;height: 50px;opacity: 0;
            position: absolute;
            top: 0;
            bottom: 0;
            right: 0;
            left: 0;
            z-index: 100;
        }
    </style>
</head>
<body>
    <div style="position: relative;width: 100px;height: 50px;">
        <input class="file" type="file" id="fafafa" name="afafaf" />
        <a class="upload">上传</a>
    </div>
    <input type="button" value="提交XHR" onclick="uploadXHR();">
    <script>
        //使用原生ajax实现上传
         function uploadXHR(){
            //首先获取值
            //$("#fafafa")[0]==document.getElementById("fafafa")
            //files表示你要上传的文件,上传的file可能有多个,但是我们这里只有一个所以是0,
            var file_obj=document.getElementById("fafafa").files[0]; //拿文件的话要加.files,这就取出了要上传的文件对象
            //这里file_obj是对象,send发送的是字符串,所以不能直接发送
            var formdata=new FormData();//FormData表示是一个form表单
            formdata.append("username","root");//可以加普通的值如key ,value
            formdata.append("fafafa",file_obj);//可以加对象
            //设置原生ajax对象
            var xhr= new XMLHttpRequest();
            xhr.open("POST","/upload_file/",true);
            //回调函数,当状态变化时触发
            xhr.onreadystatechange=function () {
                if(xhr.readyState == 4){
                  //表示接收完毕
                  console.log(xhr.responseText);
                  var obj = JSON.parse(xhr.responseText);
                  console.log(obj)
                  }
            };
            //上传文件不需要设置请求头
            xhr.send(formdata);//发送的数据只能是字符串
 }
    </script>
</body>
</html>

views.py:

def upload(request):
    return render(request,'upload.html')
def upload_file(request):
        username=request.POST.get("username")
        file_obj=request.FILES.get("fafafa")
        print(username,file_obj)
        with open(file_obj.name,'wb') as f:
            for item in file_obj.chunks():
                f.write(item)
        ret={"status":False,"data":request.POST.get("username")}
        return HttpResponse(json.dumps(ret))

测试一下:

图片.png

图片.png

图片.png

#可以看到文件上传上来了。基于原生的ajax是可以上传文件的,但是要借助于FormData()这个方法。

3.2 ajax jquery实现上传

upload.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .upload{
            display: inline-block;padding: 10px;
            background-color: brown;
            position: absolute;
            top: 0;
            bottom: 0;
            right: 0;
            left: 0;
            z-index: 90;
        }
        .file{
            width: 100px;height: 50px;opacity: 0;
            position: absolute;
            top: 0;
            bottom: 0;
            right: 0;
            left: 0;
            z-index: 100;
        }
    </style>
</head>
<body>
    <div style="position: relative;width: 100px;height: 50px;">
        <input class="file" type="file" id="fafafa" name="afafaf" />
        <a class="upload">上传</a>
    </div>
    <input type="button" value="提交jqury" onclick="uploadJquery();">
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        //jqury实现上传
        function uploadJquery(){
             //首先获取值
            //$("#fafafa")[0]==document.getElementById("fafafa")
            //files表示你要上传的文件,上传的file可能有多个,但是我们这里只有一个所以是0,
            var file_obj=document.getElementById("fafafa").files[0]
            //这里file_obj是对象,send发送的是字符串,所以不能直接发送
            var formdata=new FormData();//FormData表示是一个form表单
            formdata.append("username","root");//key ,value
            formdata.append("fafafa",file_obj);//可以加对象,可以被send发送

        $.ajax({
                url: '/upload_file/',
                type: 'POST',
                data: formdata,
                processData: false,  //tell jQuery not to process the data上传文件要设置,告诉jqury不要做特殊的处理
                contentType: false,  //tell jQuery not to set contentType上传文件要设置,告诉jqury不要做特殊的处理
                success:function(arg,a1,a2){
                    console.log(arg);
                    console.log(a1);
                    console.log(a2);
                }
            })
        }
    </script>
</body>
</html>

图片.png

3.3 iframe实现上传

upload.html:

<body>
<form id="form1" action="/upload_file/" method="POST" enctype="multipart/form-data" target="ifm1">
    <iframe id="ifm1" name="ifm1" style="display: none;"></iframe>
    <input type="file" name="fafafa" />
    <input type="submit" onclick="iframeSubmit();" value="Form提交"/>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script>
    function iframeSubmit(){
        $('#ifm1').load(function(){
            var text = $('#ifm1').contents().find('body').text();
            var obj = JSON.parse(text);
        })
    }
</script>
</body>

图片.png

四、图片上传并能预览

先来一个点击提交才能预览图片的方式:

views.py:

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)   #指定图片的上传位置,就是将图片上传到static/imgs/目录下
    with open(img_path,'wb') as f:
        for item in fafafa.chunks():
            f.write(item)
    ret = {'code': True , 'data': img_path}
    import json
    return HttpResponse(json.dumps(ret))

upload.html :

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
    <form id="form1" action="/upload_file/" method="POST" enctype="multipart/form-data" target="ifm1">
        <iframe id="ifm1" name="ifm1" style="display: none;"></iframe>
        <input type="file" name="fafafa" />
        <input type="submit" onclick="iframeSubmit();" value="Form提交"/>
    </form>
    <div id="preview"></div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function iframeSubmit(){
            $('#ifm1').load(function(){
                var text = $('#ifm1').contents().find('body').text();
                var obj = JSON.parse(text);
                console.log(obj,obj.data);

                $('#preview').empty(); //先清空
                var imgTag = document.createElement('img'); //先创建个img标签
                imgTag.src = "/" + obj.data; //给img标签增加一个src地址,因为抓到的obj.data前面少个/,所以要拼接一下。
                $('#preview').append(imgTag); //添加一个imgTag标签
            })
        }
    </script>
</body>
</html>

测试一下:

图片.png

再来一个只要上传图片不管提交不提交呢都会出现预览效果:

upload.html:

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
    <form id="form1" action="/upload_file/" method="POST" enctype="multipart/form-data" target="ifm1">
        <iframe id="ifm1" name="ifm1" style="display: none;"></iframe>
        <input type="file" name="fafafa" onchange="changeUpalod();" />  <!--绑定一个onchange事件,只要状态改变就触发changeUpalod()-->
        <input type="submit" onclick="iframeSubmit();" value="Form提交"/>
    </form>
    <div id="preview"></div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        //只要选择完图片就触发下面的函数产生预览效果
        function changeUpalod(){
            $('#ifm1').load(function(){
                var text = $('#ifm1').contents().find('body').text();
                var obj = JSON.parse(text);

                $('#preview').empty();
                var imgTag = document.createElement('img');
                imgTag.src = "/" + obj.data;
                $('#preview').append(imgTag);
            });
            //$('#form1').submit();  //注意这里,如果有这里就不需要下面的提交按钮了,它就是会将整个form1表单提交了,里面又iframe,图片也就跟着提交上去了。
         }
        function iframeSubmit(){
            $('#ifm1').load(function(){
                var text = $('#ifm1').contents().find('body').text();
                var obj = JSON.parse(text);
                console.log(obj,obj.data);

                $('#preview').empty();
                var imgTag = document.createElement('img');
                imgTag.src = "/" + obj.data;
                $('#preview').append(imgTag);
            })
        }
    </script>
</body>
</html>

测试一下:

图片.png

作者:chaishaopeng 分类:Django学习 浏览:929 评论:0
留言列表
发表评论
来宾的头像