3期 61-1 django文件上传

一、【 Form表单 文件上传

提交数据后,页面自动刷新。

1、基本使用

原理 :使用type为“file”的input框。

  • form表单必须加上属性 enctype="multipart/form-data"
  • 使用request.Files接收
  • 文件对象有name、size、chunks
def upload(request):
    if request.method == 'GET':
        return render(request, 'upload.html')
    else:
        print(request.POST)     # <QueryDict: {'user': ['张小静'], '提交': ['提交'], 'csrfmiddlewaretoken': ['WLovl00fInI6casPsGh0HrZwRcWtjT3sPlxtCSS9yQXrGF5YLNToNVLaKSfRQwAB']}>
        print(request.FILES)    # <MultiValueDict: {'img': [<InMemoryUploadedFile: 1.jpg (image/jpeg)>]}>

        user = request.POST.get('user')
        img = request.FILES.get('img')     # 获取到的是一个文件对象

        print(img.name)         # 101101.jpg     文件名称
        print(img.size)         # 84067          文件大小
        print(img.chunks)       # <bound method InMemoryUploadedFile.chunks of <InMemoryUploadedFile: 101101.jpg (image/jpeg)>>

        f = open(img.name, 'wb')    # 服务器端创建一个文件f
        for line in img.chunks():
            f.write(line)
        f.close()

        return HttpResponse('上传成功!')
Views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--enctype="multipart/form-data" 必须写-->
<form action="/upload.html", method="POST" enctype="multipart/form-data">
    会员姓名:<input type="text" name="user"><br>
    会员头像:<input type="file" name="img"><br>
    <input type="submit" name="提交">
    {% csrf_token %}
</form>

</body>
</html>
html

2、基于Form组件

原理:可用django的Form组件自动生成input框及处理提交的数据。

from django import forms
from django.forms import fields

class UploadForm(forms.Form):
    user = fields.CharField()
    img = fields.FileField()


def upload_by_form(request):
    if request.method == 'GET':
        return render(request, 'upload3.html')
    else:
        uform_obj = UploadForm(request.POST, request.FILES)     # 注意:要写上request.FILES
        if uform_obj.is_valid():
            user = uform_obj.cleaned_data['user']
            img = uform_obj.cleaned_data['img']
            f = open(img.name, 'wb')
            for line in img.chunks():
                f.write(line)
            f.close()
            return HttpResponse('上传成功3')
        else:
            return render(request, 'upload3.html')
Views.py

 

二、【 Iframe标签+Form表单 】文件上传

提交数据后,页面不自动刷新。兼容性强。

原理:form表单提交数据,iframe作为通道。

def upload1(request):
    if request.method == 'GET':
        return render(request, 'upload1.html')
    else:
        user = request.POST.get('user')
        img = request.FILES.get('img')     # 获取到的是一个文件对象

        f = open(img.name, 'wb')           # 服务器端创建一个文件f
        for line in img.chunks():
            f.write(line)
        f.close()

        return HttpResponse('上传成功!')
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--iframe作为通道+form提交数据 配合使用,不刷新页面的情况下上传文件-->
<!--要点:form表单的target属性值要等于iframe标签的name值-->
<iframe style="display:none" name="ifra"></iframe>
<form action="/upload.html", method="POST" enctype="multipart/form-data" target="ifra">
    会员姓名:<input type="text" name="user"><br>
    会员头像:<input type="file" name="img"><br>
    <input type="submit" name="提交">
    {% csrf_token %}
</form>

</body>
</html>
View Code

 实例:上传图片后,立即预览

def upload_show(request):
    if request.method == 'GET':
        return render(request, 'upload_show.html')
    else:
        user = request.POST.get('user')
        file_obj = request.FILES.get('img')     # 获取到的是一个文件对象

        import uuid
        nid = str(uuid.uuid4())

        # 制作要保存文件的路径
        import os
        file_path = os.path.join("static\images", nid+"-"+file_obj.name)

        # 将文件保存在指定路径
        f = open(file_path, 'wb')
        for line in file_obj.chunks():
            f.write(line)
        f.close()

        dic = {"status": True, "data": file_path}
        import json
        ret = json.dumps(dic)

        return HttpResponse(ret)
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="preview"></div>
<!--iframe作为通道+form提交数据 配合使用,不刷新页面的情况下上传文件-->
<iframe id="iframe" style="display:none" name="ifra"></iframe>
<form id="fm" action="/upload_show.html", method="POST" enctype="multipart/form-data" target="ifra">
    会员姓名:<input type="text" name="user"><br>
    会员头像:<input type="file" name="img"><br>
    <button onclick="AjaxSubmit5()">提交</button>
    {% csrf_token %}
</form>

<script src="/static/jquery-3.2.1.js"></script>
<script>
    function  AjaxSubmit5(){
            // 需要回调函数接收服务器发回的数据时,通过加onload事件实现
            //点击按钮后,先给iframe绑定onload事件。因为iframe接收到服务器返回的信息时,有重新加载的过程
            document.getElementById("iframe").onload = reLoadIframe;  //reloadIFrame就相当于回调函数了
            //form表达提交数据
            document.getElementById("fm").submit()
    }

    function reLoadIframe(){
            var content = this.contentWindow.document.body.innerHTML;   //接收服务器发回的信息
            console.log(content);
            var obj = JSON.parse(content);

            if (obj.status){
                // 新建img元素
                var tag = document.createElement('img');
                tag.src = obj.data;
                tag.width = 200;
                tag.height = 200;
                $('#preview').empty().append(tag);
            }
    }
</script>


</body>
</html>
View Code

 

三、【 Ajax 】文件上传

提交数据后,页面自动刷新。

原理:先将数据封装在FormData对象中,然后基于XMLHttpResponse对象发送给服务器。

1、原生XMLHttpResponse方式

def upload5(request):
    if request.method == 'GET':
        return render(request, 'upload5.html')
    else:
        print(request.POST)
        user = request.POST.get('user')
        img = request.FILES.get('img')     # 获取到的是一个文件对象

        f = open(img.name, 'wb')           # 服务器端创建一个文件f
        for line in img.chunks():
            f.write(line)
        f.close()

        return HttpResponse('上传成功!')
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    会员姓名:<input id="user" type="text"><br>
    会员头像:<input id="img" type="file"><br>
    <button id="btn" onclick="func1()">提交</button>
</body>
<script src="/static/jquery-3.2.1.js"></script>
<script>
    function func1(){
        //-------------第一步:创建并封装formdata对象------------------------------------

        // 创建 FormData对象
        var fdata_obj = new FormData();

        // 把用户输入的 user值提取出来,赋值给FormData对象
        var user = $("#user").val();
        fdata_obj.append('user', user );

        // 把用户传入的文件对象提取出来,赋值给FormData对象
        var file_obj = $("#img")[0].files[0];
        fdata_obj.append('img', file_obj);
        //-----------------------------------------------------------------------------

        //-------------第二步:通过XMLHttpResponse方式发送formdata对象--------------------

        // 创建XMLHttpRequest对象
        var xhr = new XMLHttpRequest();

        // onreadystatechange表示状态每改变一次,函数就被触发执行一次
        xhr.onreadystatechange = function () {       // 发挥回调函数的功能
            if (xhr.readyState == 4) {
                // 接收完毕服务器返回的数据
                console.log(xhr.responseText);
            }
        };

        xhr.open('GET', '/ajax1.html?p=222');
        xhr.send(fdata_obj);                          // 发送formdata对象
    }
    //---------------------------------------------------------------------------------
</script>
</html>
View Code

2、ajax方式

ajax底层是基于XMLHttpResponse的。

def upload4(request):
    if request.method == 'GET':
        return render(request, 'upload4.html')
    else:
        print(request.POST)
        user = request.POST.get('user')
        img = request.FILES.get('img')     # 获取到的是一个文件对象

        f = open(img.name, 'wb')           # 服务器端创建一个文件f
        for line in img.chunks():
            f.write(line)
        f.close()

        return HttpResponse('上传成功!')
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    会员姓名:<input id="user" type="text"><br>
    会员头像:<input id="img" type="file"><br>
    <button id="btn" onclick="func1()">提交</button>
</body>
<script src="/static/jquery-3.2.1.js"></script>
<script>
    function func1(){
        //-------------第一步:创建并封装formdata对象---------------------

        // 创建 FormData对象
        var fdata_obj = new FormData();

        // 把用户输入的 user值提取出来,赋值给FormData对象
        var user = $("#user").val();
        fdata_obj.append('user', user );  // 注意添加值的写法

        // 把用户传入的文件对象提取出来,赋值给FormData对象
        var file_obj = $("#img")[0].files[0];
        fdata_obj.append('img', file_obj);
        //--------------------------------------------------------------

        //-------------第二步:通过ajax发送formdata对象---------------------
        $.ajax({
            url: '/upload4.html',
            type:"POST",
            data:fdata_obj,            // 发送formdata对象
            success:function(arg){
                console.log(arg)
            },
            // 通过ajax传文件,必须设置以下两个参数:
            processData: false,  // tell jQuery not to process the data
            contentType: false   // tell jQuery not to set contentType
        });

        //---------------------------------------------------------------
    }
</script>
</html>
View Code

 

 

补充:

(1)对上传按钮进行美化

原理:真正上传文件的input框的opacity调成0,与自定义的好看的按钮下叠加。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
好看的上传按钮

<form action="/upload2.html", method="POST" enctype="multipart/form-data">
    <input type="text" name="user">
    <div style="position:relative">
        <a>好看的上传按钮</a>
        <input type="file" name="img" style="opacity:0.2;position:absolute;top:0;left:0">   <!--opacity调成0,与好看的按钮下叠加-->
    </div>
    <input type="submit" name="提交">

    {% csrf_token %}
</form>

</body>
</html>

html
View Code

 

代码文档:day61-文件上传

posted @ 2018-02-26 12:46  seaidler  阅读(103)  评论(0编辑  收藏  举报